2 # This file is used to define checkpoints used by ECC tool
4 # Copyright (c) 2008 - 2010, 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
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.
15 from CommonDataClass
.DataClass
import *
16 from Common
.DataType
import SUP_MODULE_LIST_STRING
, TAB_VALUE_SPLIT
17 from EccToolError
import *
23 # This class is to define checkpoints used by ECC tool
25 # @param object: Inherited from object class
31 # Check all required checkpoints
34 self
.MetaDataFileCheck()
36 self
.IncludeFileCheck()
37 self
.PredicateExpressionCheck()
38 self
.DeclAndDataTypeCheck()
39 self
.FunctionLayoutCheck()
40 self
.NamingConventionCheck()
43 def GeneralCheck(self
):
44 self
.GeneralCheckNonAcsii()
46 # Check whether file has non ACSII char
47 def GeneralCheckNonAcsii(self
):
48 if EccGlobalData
.gConfig
.GeneralCheckNonAcsii
== '1' or EccGlobalData
.gConfig
.GeneralCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
49 EdkLogger
.quiet("Checking Non-ACSII char in file ...")
50 SqlCommand
= """select ID, FullPath, ExtName from File"""
51 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
52 for Record
in RecordSet
:
53 if Record
[2].upper() not in EccGlobalData
.gConfig
.BinaryExtList
:
54 op
= open(Record
[1]).readlines()
62 OtherMsg
= "File %s has Non-ASCII char at line %s column %s" % (Record
[1], IndexOfLine
, IndexOfChar
)
63 EccGlobalData
.gDb
.TblReport
.Insert(ERROR_GENERAL_CHECK_NON_ACSII
, OtherMsg
=OtherMsg
, BelongsToTable
='File', BelongsToItem
=Record
[0])
65 # C Function Layout Checking
66 def FunctionLayoutCheck(self
):
67 self
.FunctionLayoutCheckReturnType()
68 self
.FunctionLayoutCheckModifier()
69 self
.FunctionLayoutCheckName()
70 self
.FunctionLayoutCheckPrototype()
71 self
.FunctionLayoutCheckBody()
72 self
.FunctionLayoutCheckLocalVariable()
75 IgnoredPattern
= c
.GetIgnoredDirListPattern()
76 for Dirpath
, Dirnames
, Filenames
in os
.walk(EccGlobalData
.gTarget
):
78 Dirname
= os
.path
.join(Dirpath
, Dir
)
79 if os
.path
.islink(Dirname
):
80 Dirname
= os
.path
.realpath(Dirname
)
81 if os
.path
.isdir(Dirname
):
82 # symlinks to directories are treated as directories
84 Dirnames
.append(Dirname
)
85 if IgnoredPattern
.match(Dirpath
.upper()):
87 yield (Dirpath
, Dirnames
, Filenames
)
89 # Check whether return type exists and in the first line
90 def FunctionLayoutCheckReturnType(self
):
91 if EccGlobalData
.gConfig
.CFunctionLayoutCheckReturnType
== '1' or EccGlobalData
.gConfig
.CFunctionLayoutCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
92 EdkLogger
.quiet("Checking function layout return type ...")
94 # for Dirpath, Dirnames, Filenames in self.WalkTree():
96 # if os.path.splitext(F)[1] in ('.c', '.h'):
97 # FullName = os.path.join(Dirpath, F)
98 # c.CheckFuncLayoutReturnType(FullName)
99 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
100 c
.CheckFuncLayoutReturnType(FullName
)
102 # Check whether any optional functional modifiers exist and next to the return type
103 def FunctionLayoutCheckModifier(self
):
104 if EccGlobalData
.gConfig
.CFunctionLayoutCheckOptionalFunctionalModifier
== '1' or EccGlobalData
.gConfig
.CFunctionLayoutCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
105 EdkLogger
.quiet("Checking function layout modifier ...")
107 # for Dirpath, Dirnames, Filenames in self.WalkTree():
108 # for F in Filenames:
109 # if os.path.splitext(F)[1] in ('.c', '.h'):
110 # FullName = os.path.join(Dirpath, F)
111 # c.CheckFuncLayoutModifier(FullName)
112 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
113 c
.CheckFuncLayoutModifier(FullName
)
115 # Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list
116 # Check whether the closing parenthesis is on its own line and also indented two spaces
117 def FunctionLayoutCheckName(self
):
118 if EccGlobalData
.gConfig
.CFunctionLayoutCheckFunctionName
== '1' or EccGlobalData
.gConfig
.CFunctionLayoutCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
119 EdkLogger
.quiet("Checking function layout function name ...")
121 # for Dirpath, Dirnames, Filenames in self.WalkTree():
122 # for F in Filenames:
123 # if os.path.splitext(F)[1] in ('.c', '.h'):
124 # FullName = os.path.join(Dirpath, F)
125 # c.CheckFuncLayoutName(FullName)
126 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
127 c
.CheckFuncLayoutName(FullName
)
129 # Check whether the function prototypes in include files have the same form as function definitions
130 def FunctionLayoutCheckPrototype(self
):
131 if EccGlobalData
.gConfig
.CFunctionLayoutCheckFunctionPrototype
== '1' or EccGlobalData
.gConfig
.CFunctionLayoutCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
132 EdkLogger
.quiet("Checking function layout function prototype ...")
134 # for Dirpath, Dirnames, Filenames in self.WalkTree():
135 # for F in Filenames:
136 # if os.path.splitext(F)[1] in ('.c'):
137 # FullName = os.path.join(Dirpath, F)
138 # EdkLogger.quiet("[PROTOTYPE]" + FullName)
139 # c.CheckFuncLayoutPrototype(FullName)
140 for FullName
in EccGlobalData
.gCFileList
:
141 EdkLogger
.quiet("[PROTOTYPE]" + FullName
)
142 c
.CheckFuncLayoutPrototype(FullName
)
144 # Check whether the body of a function is contained by open and close braces that must be in the first column
145 def FunctionLayoutCheckBody(self
):
146 if EccGlobalData
.gConfig
.CFunctionLayoutCheckFunctionBody
== '1' or EccGlobalData
.gConfig
.CFunctionLayoutCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
147 EdkLogger
.quiet("Checking function layout function body ...")
149 # for Dirpath, Dirnames, Filenames in self.WalkTree():
150 # for F in Filenames:
151 # if os.path.splitext(F)[1] in ('.c'):
152 # FullName = os.path.join(Dirpath, F)
153 # c.CheckFuncLayoutBody(FullName)
154 for FullName
in EccGlobalData
.gCFileList
:
155 c
.CheckFuncLayoutBody(FullName
)
157 # Check whether the data declarations is the first code in a module.
158 # self.CFunctionLayoutCheckDataDeclaration = 1
159 # Check whether no initialization of a variable as part of its declaration
160 def FunctionLayoutCheckLocalVariable(self
):
161 if EccGlobalData
.gConfig
.CFunctionLayoutCheckNoInitOfVariable
== '1' or EccGlobalData
.gConfig
.CFunctionLayoutCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
162 EdkLogger
.quiet("Checking function layout local variables ...")
164 # for Dirpath, Dirnames, Filenames in self.WalkTree():
165 # for F in Filenames:
166 # if os.path.splitext(F)[1] in ('.c'):
167 # FullName = os.path.join(Dirpath, F)
168 # c.CheckFuncLayoutLocalVariable(FullName)
170 for FullName
in EccGlobalData
.gCFileList
:
171 c
.CheckFuncLayoutLocalVariable(FullName
)
173 # Check whether no use of STATIC for functions
174 # self.CFunctionLayoutCheckNoStatic = 1
176 # Declarations and Data Types Checking
177 def DeclAndDataTypeCheck(self
):
178 self
.DeclCheckNoUseCType()
179 self
.DeclCheckInOutModifier()
180 self
.DeclCheckEFIAPIModifier()
181 self
.DeclCheckEnumeratedType()
182 self
.DeclCheckStructureDeclaration()
183 self
.DeclCheckSameStructure()
184 self
.DeclCheckUnionType()
187 # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files.
188 def DeclCheckNoUseCType(self
):
189 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckNoUseCType
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
190 EdkLogger
.quiet("Checking Declaration No use C type ...")
192 # for Dirpath, Dirnames, Filenames in self.WalkTree():
193 # for F in Filenames:
194 # if os.path.splitext(F)[1] in ('.h', '.c'):
195 # FullName = os.path.join(Dirpath, F)
196 # c.CheckDeclNoUseCType(FullName)
197 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
198 c
.CheckDeclNoUseCType(FullName
)
200 # 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
201 def DeclCheckInOutModifier(self
):
202 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckInOutModifier
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
203 EdkLogger
.quiet("Checking Declaration argument modifier ...")
205 # for Dirpath, Dirnames, Filenames in self.WalkTree():
206 # for F in Filenames:
207 # if os.path.splitext(F)[1] in ('.h', '.c'):
208 # FullName = os.path.join(Dirpath, F)
209 # c.CheckDeclArgModifier(FullName)
210 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
211 c
.CheckDeclArgModifier(FullName
)
213 # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols
214 def DeclCheckEFIAPIModifier(self
):
215 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckEFIAPIModifier
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
218 # Check whether Enumerated Type has a 'typedef' and the name is capital
219 def DeclCheckEnumeratedType(self
):
220 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckEnumeratedType
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
221 EdkLogger
.quiet("Checking Declaration enum typedef ...")
223 # for Dirpath, Dirnames, Filenames in self.WalkTree():
224 # for F in Filenames:
225 # if os.path.splitext(F)[1] in ('.h', '.c'):
226 # FullName = os.path.join(Dirpath, F)
227 # EdkLogger.quiet("[ENUM]" + FullName)
228 # c.CheckDeclEnumTypedef(FullName)
229 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
230 EdkLogger
.quiet("[ENUM]" + FullName
)
231 c
.CheckDeclEnumTypedef(FullName
)
233 # Check whether Structure Type has a 'typedef' and the name is capital
234 def DeclCheckStructureDeclaration(self
):
235 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckStructureDeclaration
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
236 EdkLogger
.quiet("Checking Declaration struct typedef ...")
238 # for Dirpath, Dirnames, Filenames in self.WalkTree():
239 # for F in Filenames:
240 # if os.path.splitext(F)[1] in ('.h', '.c'):
241 # FullName = os.path.join(Dirpath, F)
242 # EdkLogger.quiet("[STRUCT]" + FullName)
243 # c.CheckDeclStructTypedef(FullName)
244 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
245 EdkLogger
.quiet("[STRUCT]" + FullName
)
246 c
.CheckDeclStructTypedef(FullName
)
248 # Check whether having same Structure
249 def DeclCheckSameStructure(self
):
250 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckSameStructure
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
251 EdkLogger
.quiet("Checking same struct ...")
253 for IdentifierTable
in EccGlobalData
.gIdentifierTableList
:
254 SqlCommand
= """select ID, Name, BelongsToFile from %s where Model = %s""" % (IdentifierTable
, MODEL_IDENTIFIER_STRUCTURE
)
255 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
256 for Record
in RecordSet
:
258 if Record
[1] not in AllStructure
.keys():
259 AllStructure
[Record
[1]] = Record
[2]
261 ID
= AllStructure
[Record
[1]]
262 SqlCommand
= """select FullPath from File where ID = %s """ % ID
263 NewRecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
264 OtherMsg
= "The structure name '%s' is duplicate" % Record
[1]
265 if NewRecordSet
!= []:
266 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])
267 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE
, Record
[1]):
268 EccGlobalData
.gDb
.TblReport
.Insert(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE
, OtherMsg
=OtherMsg
, BelongsToTable
=IdentifierTable
, BelongsToItem
=Record
[0])
270 # Check whether Union Type has a 'typedef' and the name is capital
271 def DeclCheckUnionType(self
):
272 if EccGlobalData
.gConfig
.DeclarationDataTypeCheckUnionType
== '1' or EccGlobalData
.gConfig
.DeclarationDataTypeCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
273 EdkLogger
.quiet("Checking Declaration union typedef ...")
275 # for Dirpath, Dirnames, Filenames in self.WalkTree():
276 # for F in Filenames:
277 # if os.path.splitext(F)[1] in ('.h', '.c'):
278 # FullName = os.path.join(Dirpath, F)
279 # EdkLogger.quiet("[UNION]" + FullName)
280 # c.CheckDeclUnionTypedef(FullName)
281 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
282 EdkLogger
.quiet("[UNION]" + FullName
)
283 c
.CheckDeclUnionTypedef(FullName
)
285 # Predicate Expression Checking
286 def PredicateExpressionCheck(self
):
287 self
.PredicateExpressionCheckBooleanValue()
288 self
.PredicateExpressionCheckNonBooleanOperator()
289 self
.PredicateExpressionCheckComparisonNullType()
291 # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE
292 def PredicateExpressionCheckBooleanValue(self
):
293 if EccGlobalData
.gConfig
.PredicateExpressionCheckBooleanValue
== '1' or EccGlobalData
.gConfig
.PredicateExpressionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
294 EdkLogger
.quiet("Checking predicate expression Boolean value ...")
296 # for Dirpath, Dirnames, Filenames in self.WalkTree():
297 # for F in Filenames:
298 # if os.path.splitext(F)[1] in ('.c'):
299 # FullName = os.path.join(Dirpath, F)
300 # EdkLogger.quiet("[BOOLEAN]" + FullName)
301 # c.CheckBooleanValueComparison(FullName)
302 for FullName
in EccGlobalData
.gCFileList
:
303 EdkLogger
.quiet("[BOOLEAN]" + FullName
)
304 c
.CheckBooleanValueComparison(FullName
)
306 # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=).
307 def PredicateExpressionCheckNonBooleanOperator(self
):
308 if EccGlobalData
.gConfig
.PredicateExpressionCheckNonBooleanOperator
== '1' or EccGlobalData
.gConfig
.PredicateExpressionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
309 EdkLogger
.quiet("Checking predicate expression Non-Boolean variable...")
311 # for Dirpath, Dirnames, Filenames in self.WalkTree():
312 # for F in Filenames:
313 # if os.path.splitext(F)[1] in ('.c'):
314 # FullName = os.path.join(Dirpath, F)
315 # EdkLogger.quiet("[NON-BOOLEAN]" + FullName)
316 # c.CheckNonBooleanValueComparison(FullName)
317 for FullName
in EccGlobalData
.gCFileList
:
318 EdkLogger
.quiet("[NON-BOOLEAN]" + FullName
)
319 c
.CheckNonBooleanValueComparison(FullName
)
321 # Check whether a comparison of any pointer to zero must be done via the NULL type
322 def PredicateExpressionCheckComparisonNullType(self
):
323 if EccGlobalData
.gConfig
.PredicateExpressionCheckComparisonNullType
== '1' or EccGlobalData
.gConfig
.PredicateExpressionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
324 EdkLogger
.quiet("Checking predicate expression NULL pointer ...")
326 # for Dirpath, Dirnames, Filenames in self.WalkTree():
327 # for F in Filenames:
328 # if os.path.splitext(F)[1] in ('.c'):
329 # FullName = os.path.join(Dirpath, F)
330 # EdkLogger.quiet("[POINTER]" + FullName)
331 # c.CheckPointerNullComparison(FullName)
332 for FullName
in EccGlobalData
.gCFileList
:
333 EdkLogger
.quiet("[POINTER]" + FullName
)
334 c
.CheckPointerNullComparison(FullName
)
336 # Include file checking
337 def IncludeFileCheck(self
):
338 self
.IncludeFileCheckIfndef()
339 self
.IncludeFileCheckData()
340 self
.IncludeFileCheckSameName()
342 # Check whether having include files with same name
343 def IncludeFileCheckSameName(self
):
344 if EccGlobalData
.gConfig
.IncludeFileCheckSameName
== '1' or EccGlobalData
.gConfig
.IncludeFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
345 EdkLogger
.quiet("Checking same header file name ...")
346 SqlCommand
= """select ID, FullPath from File
347 where Model = 1002 order by Name """
349 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
350 for Record
in RecordSet
:
351 List
= Record
[1].replace('/', '\\').split('\\')
353 Key
= List
[-2] + '\\' + List
[-1]
356 if Key
not in RecordDict
:
357 RecordDict
[Key
] = [Record
]
359 RecordDict
[Key
].append(Record
)
361 for Key
in RecordDict
:
362 if len(RecordDict
[Key
]) > 1:
363 for Item
in RecordDict
[Key
]:
364 Path
= Item
[1].replace(EccGlobalData
.gWorkspace
, '')
365 if Path
.startswith('\\') or Path
.startswith('/'):
367 if not EccGlobalData
.gException
.IsException(ERROR_INCLUDE_FILE_CHECK_NAME
, Path
):
368 EccGlobalData
.gDb
.TblReport
.Insert(ERROR_INCLUDE_FILE_CHECK_NAME
, OtherMsg
="The file name for [%s] is duplicate" % Path
, BelongsToTable
='File', BelongsToItem
=Item
[0])
370 # Check whether all include file contents is guarded by a #ifndef statement.
371 def IncludeFileCheckIfndef(self
):
372 if EccGlobalData
.gConfig
.IncludeFileCheckIfndefStatement
== '1' or EccGlobalData
.gConfig
.IncludeFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
373 EdkLogger
.quiet("Checking header file ifndef ...")
375 # for Dirpath, Dirnames, Filenames in self.WalkTree():
376 # for F in Filenames:
377 # if os.path.splitext(F)[1] in ('.h'):
378 # FullName = os.path.join(Dirpath, F)
379 # MsgList = c.CheckHeaderFileIfndef(FullName)
380 for FullName
in EccGlobalData
.gHFileList
:
381 MsgList
= c
.CheckHeaderFileIfndef(FullName
)
383 # Check whether include files NOT contain code or define data variables
384 def IncludeFileCheckData(self
):
385 if EccGlobalData
.gConfig
.IncludeFileCheckData
== '1' or EccGlobalData
.gConfig
.IncludeFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
386 EdkLogger
.quiet("Checking header file data ...")
388 # for Dirpath, Dirnames, Filenames in self.WalkTree():
389 # for F in Filenames:
390 # if os.path.splitext(F)[1] in ('.h'):
391 # FullName = os.path.join(Dirpath, F)
392 # MsgList = c.CheckHeaderFileData(FullName)
393 for FullName
in EccGlobalData
.gHFileList
:
394 MsgList
= c
.CheckHeaderFileData(FullName
)
396 # Doxygen document checking
397 def DoxygenCheck(self
):
398 self
.DoxygenCheckFileHeader()
399 self
.DoxygenCheckFunctionHeader()
400 self
.DoxygenCheckCommentDescription()
401 self
.DoxygenCheckCommentFormat()
402 self
.DoxygenCheckCommand()
404 # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5
405 def DoxygenCheckFileHeader(self
):
406 if EccGlobalData
.gConfig
.DoxygenCheckFileHeader
== '1' or EccGlobalData
.gConfig
.DoxygenCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
407 EdkLogger
.quiet("Checking Doxygen file header ...")
409 for Dirpath
, Dirnames
, Filenames
in self
.WalkTree():
411 Ext
= os
.path
.splitext(F
)[1]
412 if Ext
in ('.h', '.c'):
413 FullName
= os
.path
.join(Dirpath
, F
)
414 MsgList
= c
.CheckFileHeaderDoxygenComments(FullName
)
415 elif Ext
in ('.inf', '.dec', '.dsc', '.fdf'):
416 FullName
= os
.path
.join(Dirpath
, F
)
417 op
= open(FullName
).readlines()
418 if not op
[0].startswith('## @file') and op
[6].startswith('## @file') and op
[7].startswith('## @file'):
419 SqlStatement
= """ select ID from File where FullPath like '%s'""" % FullName
420 ResultSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlStatement
)
421 for Result
in ResultSet
:
422 Msg
= 'INF/DEC/DSC/FDF file header comment should begin with ""## @file""'
423 EccGlobalData
.gDb
.TblReport
.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER
, Msg
, "File", Result
[0])
426 # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5
427 def DoxygenCheckFunctionHeader(self
):
428 if EccGlobalData
.gConfig
.DoxygenCheckFunctionHeader
== '1' or EccGlobalData
.gConfig
.DoxygenCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
429 EdkLogger
.quiet("Checking Doxygen function header ...")
431 # for Dirpath, Dirnames, Filenames in self.WalkTree():
432 # for F in Filenames:
433 # if os.path.splitext(F)[1] in ('.h', '.c'):
434 # FullName = os.path.join(Dirpath, F)
435 # MsgList = c.CheckFuncHeaderDoxygenComments(FullName)
436 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
437 MsgList
= c
.CheckFuncHeaderDoxygenComments(FullName
)
440 # Check whether the first line of text in a comment block is a brief description of the element being documented.
441 # The brief description must end with a period.
442 def DoxygenCheckCommentDescription(self
):
443 if EccGlobalData
.gConfig
.DoxygenCheckCommentDescription
== '1' or EccGlobalData
.gConfig
.DoxygenCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
446 # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.
447 def DoxygenCheckCommentFormat(self
):
448 if EccGlobalData
.gConfig
.DoxygenCheckCommentFormat
== '1' or EccGlobalData
.gConfig
.DoxygenCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
449 EdkLogger
.quiet("Checking Doxygen comment ///< ...")
451 # for Dirpath, Dirnames, Filenames in self.WalkTree():
452 # for F in Filenames:
453 # if os.path.splitext(F)[1] in ('.h', '.c'):
454 # FullName = os.path.join(Dirpath, F)
455 # MsgList = c.CheckDoxygenTripleForwardSlash(FullName)
456 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
457 MsgList
= c
.CheckDoxygenTripleForwardSlash(FullName
)
459 # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.
460 def DoxygenCheckCommand(self
):
461 if EccGlobalData
.gConfig
.DoxygenCheckCommand
== '1' or EccGlobalData
.gConfig
.DoxygenCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
462 EdkLogger
.quiet("Checking Doxygen command ...")
464 # for Dirpath, Dirnames, Filenames in self.WalkTree():
465 # for F in Filenames:
466 # if os.path.splitext(F)[1] in ('.h', '.c'):
467 # FullName = os.path.join(Dirpath, F)
468 # MsgList = c.CheckDoxygenCommand(FullName)
469 for FullName
in EccGlobalData
.gCFileList
+ EccGlobalData
.gHFileList
:
470 MsgList
= c
.CheckDoxygenCommand(FullName
)
472 # Meta-Data File Processing Checking
473 def MetaDataFileCheck(self
):
474 self
.MetaDataFileCheckPathName()
475 self
.MetaDataFileCheckGenerateFileList()
476 self
.MetaDataFileCheckLibraryInstance()
477 self
.MetaDataFileCheckLibraryInstanceDependent()
478 self
.MetaDataFileCheckLibraryInstanceOrder()
479 self
.MetaDataFileCheckLibraryNoUse()
480 self
.MetaDataFileCheckBinaryInfInFdf()
481 self
.MetaDataFileCheckPcdDuplicate()
482 self
.MetaDataFileCheckPcdFlash()
483 self
.MetaDataFileCheckPcdNoUse()
484 self
.MetaDataFileCheckGuidDuplicate()
485 self
.MetaDataFileCheckModuleFileNoUse()
486 self
.MetaDataFileCheckPcdType()
487 self
.MetaDataFileCheckModuleFileGuidDuplication()
489 # Check whether each file defined in meta-data exists
490 def MetaDataFileCheckPathName(self
):
491 if EccGlobalData
.gConfig
.MetaDataFileCheckPathName
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
492 # This item is covered when parsing Inf/Dec/Dsc files
495 # Generate a list for all files defined in meta-data files
496 def MetaDataFileCheckGenerateFileList(self
):
497 if EccGlobalData
.gConfig
.MetaDataFileCheckGenerateFileList
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
498 # This item is covered when parsing Inf/Dec/Dsc files
501 # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.
502 # Each Library Instance must specify the Supported Module Types in its Inf file,
503 # and any module specifying the library instance must be one of the supported types.
504 def MetaDataFileCheckLibraryInstance(self
):
505 if EccGlobalData
.gConfig
.MetaDataFileCheckLibraryInstance
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
506 EdkLogger
.quiet("Checking for library instance type issue ...")
507 SqlCommand
= """select A.ID, A.Value2, B.Value2 from Inf as A left join Inf as B
508 where A.Value1 = 'LIBRARY_CLASS' and A.Model = %s
509 and B.Value1 = 'MODULE_TYPE' and B.Model = %s and A.BelongsToFile = B.BelongsToFile
510 group by A.BelongsToFile""" % (MODEL_META_DATA_HEADER
, MODEL_META_DATA_HEADER
)
511 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
513 for Record
in RecordSet
:
514 List
= Record
[1].split('|', 1)
517 SupModType
= SUP_MODULE_LIST_STRING
.split(TAB_VALUE_SPLIT
)
519 SupModType
= List
[1].split()
521 if List
[0] not in LibraryClasses
:
522 LibraryClasses
[List
[0]] = SupModType
524 for Item
in SupModType
:
525 if Item
not in LibraryClasses
[List
[0]]:
526 LibraryClasses
[List
[0]].append(Item
)
528 if Record
[2] != 'BASE' and Record
[2] not in SupModType
:
529 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])
531 SqlCommand
= """select A.ID, A.Value1, B.Value2 from Inf as A left join Inf as B
532 where A.Model = %s and B.Value1 = '%s' and B.Model = %s
533 and B.BelongsToFile = A.BelongsToFile""" \
534 % (MODEL_EFI_LIBRARY_CLASS
, 'MODULE_TYPE', MODEL_META_DATA_HEADER
)
535 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
536 # Merge all LibraryClasses' supmodlist
538 for Record
in RecordSet
:
539 if Record
[1] not in RecordDict
:
540 RecordDict
[Record
[1]] = [str(Record
[2])]
542 if Record
[2] not in RecordDict
[Record
[1]]:
543 RecordDict
[Record
[1]].append(Record
[2])
545 for Record
in RecordSet
:
546 if Record
[1] in LibraryClasses
:
547 if Record
[2] not in LibraryClasses
[Record
[1]] and 'BASE' not in RecordDict
[Record
[1]]:
548 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1
, Record
[1]):
549 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])
551 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1
, Record
[1]):
552 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])
554 # Check whether a Library Instance has been defined for all dependent library classes
555 def MetaDataFileCheckLibraryInstanceDependent(self
):
556 if EccGlobalData
.gConfig
.MetaDataFileCheckLibraryInstanceDependent
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
557 EdkLogger
.quiet("Checking for library instance dependent issue ...")
558 SqlCommand
= """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS
559 LibraryClasses
= EccGlobalData
.gDb
.TblDsc
.Exec(SqlCommand
)
560 for LibraryClass
in LibraryClasses
:
561 if LibraryClass
[1].upper() != 'NULL':
562 LibraryIns
= os
.path
.normpath(os
.path
.join(EccGlobalData
.gWorkspace
, LibraryClass
[2]))
563 SqlCommand
= """select Value2 from Inf where BelongsToFile =
564 (select ID from File where lower(FullPath) = lower('%s'))
565 and Value1 = '%s'""" % (LibraryIns
, 'LIBRARY_CLASS')
566 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
568 for Record
in RecordSet
:
569 LibName
= Record
[0].split('|', 1)[0]
570 if LibraryClass
[1] == LibName
:
573 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT
, LibraryClass
[1]):
574 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])
576 # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies
577 def MetaDataFileCheckLibraryInstanceOrder(self
):
578 if EccGlobalData
.gConfig
.MetaDataFileCheckLibraryInstanceOrder
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
579 # This checkpoint is not necessary for Ecc check
582 # Check whether the unnecessary inclusion of library classes in the Inf file
583 # Check whether the unnecessary duplication of library classe names in the DSC file
584 def MetaDataFileCheckLibraryNoUse(self
):
585 if EccGlobalData
.gConfig
.MetaDataFileCheckLibraryNoUse
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
586 EdkLogger
.quiet("Checking for library instance not used ...")
587 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
)
588 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
589 for Record
in RecordSet
:
590 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE
, Record
[1]):
591 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])
593 select A.ID, A.Value1, A.BelongsToFile, A.StartLine, B.StartLine from Dsc as A left join Dsc as B
594 where A.Model = %s and B.Model = %s and A.Value3 = B.Value3 and A.Arch = B.Arch and A.ID <> B.ID
595 and A.Value1 = B.Value1 and A.StartLine <> B.StartLine and B.BelongsToFile = A.BelongsToFile""" \
596 % (MODEL_EFI_LIBRARY_CLASS
, MODEL_EFI_LIBRARY_CLASS
)
597 RecordSet
= EccGlobalData
.gDb
.TblDsc
.Exec(SqlCommand
)
598 for Record
in RecordSet
:
599 if Record
[3] and Record
[4] and Record
[3] != Record
[4]:
600 SqlCommand
= """select FullPath from File where ID = %s""" % (Record
[2])
601 FilePathList
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
602 for FilePath
in FilePathList
:
603 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NAME_DUPLICATE
, Record
[1]):
604 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])
606 # 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
607 def MetaDataFileCheckBinaryInfInFdf(self
):
608 if EccGlobalData
.gConfig
.MetaDataFileCheckBinaryInfInFdf
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
609 EdkLogger
.quiet("Checking for non-binary modules defined in FDF files ...")
610 SqlCommand
= """select A.ID, A.Value1 from Fdf as A
614 (select B.Value1 from Dsc as B
616 and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT
, MODEL_META_DATA_COMPONENT
)
617 RecordSet
= EccGlobalData
.gDb
.TblFdf
.Exec(SqlCommand
)
618 for Record
in RecordSet
:
621 FilePath
= os
.path
.normpath(os
.path
.join(EccGlobalData
.gWorkspace
, FilePath
))
622 SqlCommand
= """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')
623 """ % (MODEL_EFI_SOURCE_FILE
, FilePath
)
624 NewRecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
625 if NewRecordSet
!= []:
626 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF
, FilePath
):
627 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
)
629 # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.
630 def MetaDataFileCheckPcdDuplicate(self
):
631 if EccGlobalData
.gConfig
.MetaDataFileCheckPcdDuplicate
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
632 EdkLogger
.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...")
634 select A.ID, A.Value2, A.BelongsToFile, B.ID, B.Value2, B.BelongsToFile from Dsc as A, Fdf as B
635 where A.Model >= %s and A.Model < %s
636 and B.Model >= %s and B.Model < %s
637 and A.Value2 = B.Value2
641 """ % (MODEL_PCD
, MODEL_META_DATA_HEADER
, MODEL_PCD
, MODEL_META_DATA_HEADER
)
642 RecordSet
= EccGlobalData
.gDb
.TblDsc
.Exec(SqlCommand
)
643 for Record
in RecordSet
:
644 SqlCommand1
= """select Name from File where ID = %s""" % Record
[2]
645 SqlCommand2
= """select Name from File where ID = %s""" % Record
[5]
646 DscFileName
= os
.path
.splitext(EccGlobalData
.gDb
.TblDsc
.Exec(SqlCommand1
)[0][0])[0]
647 FdfFileName
= os
.path
.splitext(EccGlobalData
.gDb
.TblDsc
.Exec(SqlCommand2
)[0][0])[0]
648 if DscFileName
!= FdfFileName
:
650 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE
, Record
[1]):
651 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]), BelongsToTable
='Dsc', BelongsToItem
=Record
[0])
652 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE
, Record
[3]):
653 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
[4]), BelongsToTable
='Fdf', BelongsToItem
=Record
[3])
655 EdkLogger
.quiet("Checking for duplicate PCDs defined in DEC files ...")
657 select A.ID, A.Value2 from Dec as A, Dec as B
658 where A.Model >= %s and A.Model < %s
659 and B.Model >= %s and B.Model < %s
660 and A.Value2 = B.Value2
661 and ((A.Arch = B.Arch) and (A.Arch != 'COMMON' or B.Arch != 'COMMON'))
665 and A.BelongsToFile = B.BelongsToFile
667 """ % (MODEL_PCD
, MODEL_META_DATA_HEADER
, MODEL_PCD
, MODEL_META_DATA_HEADER
)
668 RecordSet
= EccGlobalData
.gDb
.TblDsc
.Exec(SqlCommand
)
669 for Record
in RecordSet
:
670 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE
, Record
[1]):
671 EccGlobalData
.gDb
.TblReport
.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE
, OtherMsg
="The PCD [%s] is defined duplicated in DEC file" % (Record
[1]), BelongsToTable
='Dec', BelongsToItem
=Record
[0])
673 # Check whether PCD settings in the FDF file can only be related to flash.
674 def MetaDataFileCheckPcdFlash(self
):
675 if EccGlobalData
.gConfig
.MetaDataFileCheckPcdFlash
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
676 EdkLogger
.quiet("Checking only Flash related PCDs are used in FDF ...")
678 select ID, Value2, BelongsToFile from Fdf as A
679 where A.Model >= %s and Model < %s
681 and A.Value2 not like '%%Flash%%'
682 """ % (MODEL_PCD
, MODEL_META_DATA_HEADER
)
683 RecordSet
= EccGlobalData
.gDb
.TblFdf
.Exec(SqlCommand
)
684 for Record
in RecordSet
:
685 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_PCD_FLASH
, Record
[1]):
686 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]), BelongsToTable
='Fdf', BelongsToItem
=Record
[0])
688 # Check whether PCDs used in Inf files but not specified in Dsc or FDF files
689 def MetaDataFileCheckPcdNoUse(self
):
690 if EccGlobalData
.gConfig
.MetaDataFileCheckPcdNoUse
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
691 EdkLogger
.quiet("Checking for non-specified PCDs ...")
693 select ID, Value2, BelongsToFile from Inf as A
694 where A.Model >= %s and Model < %s
697 (select Value2 from Dsc as B
698 where B.Model >= %s and B.Model < %s
701 (select Value2 from Fdf as C
702 where C.Model >= %s and C.Model < %s
704 """ % (MODEL_PCD
, MODEL_META_DATA_HEADER
, MODEL_PCD
, MODEL_META_DATA_HEADER
, MODEL_PCD
, MODEL_META_DATA_HEADER
)
705 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
706 for Record
in RecordSet
:
707 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE
, Record
[1]):
708 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]), BelongsToTable
='Inf', BelongsToItem
=Record
[0])
710 # Check whether having duplicate guids defined for Guid/Protocol/Ppi
711 def MetaDataFileCheckGuidDuplicate(self
):
712 if EccGlobalData
.gConfig
.MetaDataFileCheckGuidDuplicate
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
713 EdkLogger
.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...")
715 self
.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID
, MODEL_EFI_GUID
, EccGlobalData
.gDb
.TblDec
)
716 self
.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID
, MODEL_EFI_GUID
, EccGlobalData
.gDb
.TblDsc
)
717 self
.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID
, MODEL_EFI_GUID
)
719 self
.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL
, MODEL_EFI_PROTOCOL
, EccGlobalData
.gDb
.TblDec
)
720 self
.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL
, MODEL_EFI_PROTOCOL
, EccGlobalData
.gDb
.TblDsc
)
721 self
.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL
, MODEL_EFI_PROTOCOL
)
723 self
.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI
, MODEL_EFI_PPI
, EccGlobalData
.gDb
.TblDec
)
724 self
.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI
, MODEL_EFI_PPI
, EccGlobalData
.gDb
.TblDsc
)
725 self
.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI
, MODEL_EFI_PPI
)
727 # Check whether all files under module directory are described in INF files
728 def MetaDataFileCheckModuleFileNoUse(self
):
729 if EccGlobalData
.gConfig
.MetaDataFileCheckModuleFileNoUse
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
730 EdkLogger
.quiet("Checking for no used module files ...")
732 select upper(Path) from File where ID in (select BelongsToFile from INF where BelongsToFile != -1)
734 InfPathSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
736 for Item
in InfPathSet
:
737 if Item
[0] not in InfPathList
:
738 InfPathList
.append(Item
[0])
740 select ID, Path, FullPath from File where upper(FullPath) not in
741 (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B
742 where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and
743 B.BelongsToFile = A.ID and B.Model = %s)
744 and (Model = %s or Model = %s)
745 """ % (MODEL_EFI_SOURCE_FILE
, MODEL_EFI_SOURCE_FILE
, MODEL_FILE_C
, MODEL_FILE_H
)
746 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
747 for Record
in RecordSet
:
749 Path
= Path
.upper().replace('\X64', '').replace('\IA32', '').replace('\EBC', '').replace('\IPF', '').replace('\ARM', '')
750 if Path
in InfPathList
:
751 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE
, Record
[2]):
752 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])
754 # Check whether the PCD is correctly used in C function via its type
755 def MetaDataFileCheckPcdType(self
):
756 if EccGlobalData
.gConfig
.MetaDataFileCheckPcdType
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
757 EdkLogger
.quiet("Checking for pcd type in c code function usage ...")
759 select ID, Model, Value1, BelongsToFile from INF where Model > %s and Model < %s
760 """ % (MODEL_PCD
, MODEL_META_DATA_HEADER
)
761 PcdSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
765 if len(Pcd
[2].split(".")) > 1:
766 PcdName
= Pcd
[2].split(".")[1]
767 BelongsToFile
= Pcd
[3]
769 select ID from File where FullPath in
770 (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s
771 and B.ID = %s and (B.Model = %s or B.Model = %s))
772 """ % (MODEL_EFI_SOURCE_FILE
, BelongsToFile
, BelongsToFile
, MODEL_FILE_C
, MODEL_FILE_H
)
773 TableSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
775 TblName
= 'Identifier' + str(Tbl
[0])
777 select Name, ID from %s where value like '%s' and Model = %s
778 """ % (TblName
, PcdName
, MODEL_IDENTIFIER_FUNCTION_CALLING
)
779 RecordSet
= EccGlobalData
.gDb
.TblInf
.Exec(SqlCommand
)
780 TblNumber
= TblName
.replace('Identifier', '')
781 for Record
in RecordSet
:
783 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_PCD_TYPE
, FunName
):
784 if Model
in [MODEL_PCD_FIXED_AT_BUILD
] and not FunName
.startswith('FixedPcdGet'):
785 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])
786 if Model
in [MODEL_PCD_FEATURE_FLAG
] and (not FunName
.startswith('FeaturePcdGet') and not FunName
.startswith('FeaturePcdSet')):
787 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])
788 if Model
in [MODEL_PCD_PATCHABLE_IN_MODULE
] and (not FunName
.startswith('PatchablePcdGet') and not FunName
.startswith('PatchablePcdSet')):
789 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])
791 #ERROR_META_DATA_FILE_CHECK_PCD_TYPE
794 # Internal worker function to get the INF workspace relative path from FileID
795 def GetInfFilePathFromID(self
, FileID
):
796 Table
= EccGlobalData
.gDb
.TblFile
797 SqlCommand
= """select A.FullPath from %s as A where A.ID = %s""" % (Table
.Table
, FileID
)
798 RecordSet
= Table
.Exec(SqlCommand
)
800 for Record
in RecordSet
:
801 Path
= Record
[0].replace(EccGlobalData
.gWorkspace
, '')
802 if Path
.startswith('\\') or Path
.startswith('/'):
806 # Check whether two module INFs under one workspace has the same FILE_GUID value
807 def MetaDataFileCheckModuleFileGuidDuplication(self
):
808 if EccGlobalData
.gConfig
.MetaDataFileCheckModuleFileGuidDuplication
== '1' or EccGlobalData
.gConfig
.MetaDataFileCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
809 EdkLogger
.quiet("Checking for pcd type in c code function usage ...")
810 Table
= EccGlobalData
.gDb
.TblInf
812 select A.ID, A.Value2, A.BelongsToFile, B.BelongsToFile from %s as A, %s as B
813 where A.Value1 = 'FILE_GUID' and B.Value1 = 'FILE_GUID' and
814 A.Value2 = B.Value2 and A.ID <> B.ID group by A.ID
815 """ % (Table
.Table
, Table
.Table
)
816 RecordSet
= Table
.Exec(SqlCommand
)
817 for Record
in RecordSet
:
818 InfPath1
= self
.GetInfFilePathFromID(Record
[2])
819 InfPath2
= self
.GetInfFilePathFromID(Record
[3])
820 if InfPath1
and InfPath2
:
821 if not EccGlobalData
.gException
.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION
, InfPath1
):
822 Msg
= "The FILE_GUID of INF file [%s] is duplicated with that of %s" % (InfPath1
, InfPath2
)
823 EccGlobalData
.gDb
.TblReport
.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION
, OtherMsg
=Msg
, BelongsToTable
=Table
.Table
, BelongsToItem
=Record
[0])
826 # Check whether these is duplicate Guid/Ppi/Protocol name
827 def CheckGuidProtocolPpi(self
, ErrorID
, Model
, Table
):
829 if Model
== MODEL_EFI_GUID
:
831 if Model
== MODEL_EFI_PROTOCOL
:
833 if Model
== MODEL_EFI_PPI
:
836 select A.ID, A.Value1 from %s as A, %s as B
837 where A.Model = %s and B.Model = %s
838 and A.Value1 = B.Value1 and A.ID <> B.ID
843 """ % (Table
.Table
, Table
.Table
, Model
, Model
)
844 RecordSet
= Table
.Exec(SqlCommand
)
845 for Record
in RecordSet
:
846 if not EccGlobalData
.gException
.IsException(ErrorID
, Record
[1]):
847 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])
849 # Check whether these is duplicate Guid/Ppi/Protocol value
850 def CheckGuidProtocolPpiValue(self
, ErrorID
, Model
):
852 Table
= EccGlobalData
.gDb
.TblDec
853 if Model
== MODEL_EFI_GUID
:
855 if Model
== MODEL_EFI_PROTOCOL
:
857 if Model
== MODEL_EFI_PPI
:
860 select A.ID, A.Value2 from %s as A, %s as B
861 where A.Model = %s and B.Model = %s
862 and A.Value2 = B.Value2 and A.ID <> B.ID
865 """ % (Table
.Table
, Table
.Table
, Model
, Model
)
866 RecordSet
= Table
.Exec(SqlCommand
)
867 for Record
in RecordSet
:
868 if not EccGlobalData
.gException
.IsException(ErrorID
, Record
[1]):
869 EccGlobalData
.gDb
.TblReport
.Insert(ErrorID
, OtherMsg
="The %s value [%s] is used more than one time" % (Name
.upper(), Record
[1]), BelongsToTable
=Table
.Table
, BelongsToItem
=Record
[0])
871 # Naming Convention Check
872 def NamingConventionCheck(self
):
873 if EccGlobalData
.gConfig
.NamingConventionCheckDefineStatement
== '1' \
874 or EccGlobalData
.gConfig
.NamingConventionCheckTypedefStatement
== '1' \
875 or EccGlobalData
.gConfig
.NamingConventionCheckIfndefStatement
== '1' \
876 or EccGlobalData
.gConfig
.NamingConventionCheckVariableName
== '1' \
877 or EccGlobalData
.gConfig
.NamingConventionCheckSingleCharacterVariable
== '1' \
878 or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1'\
879 or EccGlobalData
.gConfig
.CheckAll
== '1':
880 for Dirpath
, Dirnames
, Filenames
in self
.WalkTree():
882 if os
.path
.splitext(F
)[1] in ('.h', '.c'):
883 FullName
= os
.path
.join(Dirpath
, F
)
884 Id
= c
.GetTableID(FullName
)
887 FileTable
= 'Identifier' + str(Id
)
888 self
.NamingConventionCheckDefineStatement(FileTable
)
889 self
.NamingConventionCheckTypedefStatement(FileTable
)
890 self
.NamingConventionCheckIfndefStatement(FileTable
)
891 self
.NamingConventionCheckVariableName(FileTable
)
892 self
.NamingConventionCheckSingleCharacterVariable(FileTable
)
894 self
.NamingConventionCheckPathName()
895 self
.NamingConventionCheckFunctionName()
897 # Check whether only capital letters are used for #define declarations
898 def NamingConventionCheckDefineStatement(self
, FileTable
):
899 if EccGlobalData
.gConfig
.NamingConventionCheckDefineStatement
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
900 EdkLogger
.quiet("Checking naming covention of #define statement ...")
902 SqlCommand
= """select ID, Value from %s where Model = %s""" % (FileTable
, MODEL_IDENTIFIER_MACRO_DEFINE
)
903 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
904 for Record
in RecordSet
:
905 Name
= Record
[1].strip().split()[1]
906 if Name
.find('(') != -1:
907 Name
= Name
[0:Name
.find('(')]
908 if Name
.upper() != Name
:
909 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT
, Name
):
910 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])
912 # Check whether only capital letters are used for typedef declarations
913 def NamingConventionCheckTypedefStatement(self
, FileTable
):
914 if EccGlobalData
.gConfig
.NamingConventionCheckTypedefStatement
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
915 EdkLogger
.quiet("Checking naming covention of #typedef statement ...")
917 SqlCommand
= """select ID, Name from %s where Model = %s""" % (FileTable
, MODEL_IDENTIFIER_TYPEDEF
)
918 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
919 for Record
in RecordSet
:
920 Name
= Record
[1].strip()
921 if Name
!= '' and Name
!= None:
923 Name
= Name
[1:Name
.find(')')]
924 if Name
.find('(') > -1:
925 Name
= Name
[Name
.find('(') + 1 : Name
.find(')')]
926 Name
= Name
.replace('WINAPI', '')
927 Name
= Name
.replace('*', '').strip()
928 if Name
.upper() != Name
:
929 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT
, Name
):
930 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])
932 # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'.
933 def NamingConventionCheckIfndefStatement(self
, FileTable
):
934 if EccGlobalData
.gConfig
.NamingConventionCheckTypedefStatement
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
935 EdkLogger
.quiet("Checking naming covention of #ifndef statement ...")
937 SqlCommand
= """select ID, Value from %s where Model = %s""" % (FileTable
, MODEL_IDENTIFIER_MACRO_IFNDEF
)
938 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
939 for Record
in RecordSet
:
940 Name
= Record
[1].replace('#ifndef', '').strip()
941 if Name
[0] != '_' or Name
[-1] != '_':
942 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT
, Name
):
943 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])
945 # Rule for path name, variable name and function name
946 # 1. First character should be upper case
947 # 2. Existing lower case in a word
948 # 3. No space existence
949 # Check whether the path name followed the rule
950 def NamingConventionCheckPathName(self
):
951 if EccGlobalData
.gConfig
.NamingConventionCheckPathName
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
952 EdkLogger
.quiet("Checking naming covention of file path name ...")
953 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
954 SqlCommand
= """select ID, Name from File"""
955 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
956 for Record
in RecordSet
:
957 if not Pattern
.match(Record
[1]):
958 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME
, Record
[1]):
959 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])
961 # Rule for path name, variable name and function name
962 # 1. First character should be upper case
963 # 2. Existing lower case in a word
964 # 3. No space existence
965 # 4. Global variable name must start with a 'g'
966 # Check whether the variable name followed the rule
967 def NamingConventionCheckVariableName(self
, FileTable
):
968 if EccGlobalData
.gConfig
.NamingConventionCheckVariableName
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
969 EdkLogger
.quiet("Checking naming covention of variable name ...")
970 Pattern
= re
.compile(r
'^[A-Zgm]+\S*[a-z]\S*$')
972 SqlCommand
= """select ID, Name from %s where Model = %s""" % (FileTable
, MODEL_IDENTIFIER_VARIABLE
)
973 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
974 for Record
in RecordSet
:
975 if not Pattern
.match(Record
[1]):
976 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Record
[1]):
977 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])
979 # Rule for path name, variable name and function name
980 # 1. First character should be upper case
981 # 2. Existing lower case in a word
982 # 3. No space existence
983 # Check whether the function name followed the rule
984 def NamingConventionCheckFunctionName(self
):
985 if EccGlobalData
.gConfig
.NamingConventionCheckFunctionName
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
986 EdkLogger
.quiet("Checking naming covention of function name ...")
987 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
988 SqlCommand
= """select ID, Name from Function"""
989 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
990 for Record
in RecordSet
:
991 if not Pattern
.match(Record
[1]):
992 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME
, Record
[1]):
993 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])
995 # Check whether NO use short variable name with single character
996 def NamingConventionCheckSingleCharacterVariable(self
, FileTable
):
997 if EccGlobalData
.gConfig
.NamingConventionCheckSingleCharacterVariable
== '1' or EccGlobalData
.gConfig
.NamingConventionCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
998 EdkLogger
.quiet("Checking naming covention of single character variable name ...")
1000 SqlCommand
= """select ID, Name from %s where Model = %s""" % (FileTable
, MODEL_IDENTIFIER_VARIABLE
)
1001 RecordSet
= EccGlobalData
.gDb
.TblFile
.Exec(SqlCommand
)
1002 for Record
in RecordSet
:
1003 Variable
= Record
[1].replace('*', '')
1004 if len(Variable
) == 1:
1005 if not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE
, Record
[1]):
1006 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])
1010 # This acts like the main() function for the script, unless it is 'import'ed into another
1013 if __name__
== '__main__':