dbfedb514bc809020d9e822da3f7c9a456708be8
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / Check.py
1 ## @file
2 # This file is used to define checkpoints used by ECC tool
3 #
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
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 #
13 import os
14 import re
15 from CommonDataClass.DataClass import *
16 from Common.DataType import SUP_MODULE_LIST_STRING, TAB_VALUE_SPLIT
17 from EccToolError import *
18 import EccGlobalData
19 import c
20
21 ## Check
22 #
23 # This class is to define checkpoints used by ECC tool
24 #
25 # @param object: Inherited from object class
26 #
27 class Check(object):
28 def __init__(self):
29 pass
30
31 # Check all required checkpoints
32 def Check(self):
33 self.MetaDataFileCheck()
34 self.DoxygenCheck()
35 self.IncludeFileCheck()
36 self.PredicateExpressionCheck()
37 self.DeclAndDataTypeCheck()
38 self.FunctionLayoutCheck()
39 self.NamingConventionCheck()
40
41 # C Function Layout Checking
42 def FunctionLayoutCheck(self):
43 self.FunctionLayoutCheckReturnType()
44 self.FunctionLayoutCheckModifier()
45 self.FunctionLayoutCheckName()
46 self.FunctionLayoutCheckPrototype()
47 self.FunctionLayoutCheckBody()
48 self.FunctionLayoutCheckLocalVariable()
49
50 def WalkTree(self):
51 IgnoredPattern = c.GetIgnoredDirListPattern()
52 for Dirpath, Dirnames, Filenames in os.walk(EccGlobalData.gTarget):
53 for Dir in Dirnames:
54 Dirname = os.path.join(Dirpath, Dir)
55 if os.path.islink(Dirname):
56 Dirname = os.path.realpath(Dirname)
57 if os.path.isdir(Dirname):
58 # symlinks to directories are treated as directories
59 Dirnames.remove(Dir)
60 Dirnames.append(Dirname)
61 if IgnoredPattern.match(Dirpath.upper()):
62 continue
63 yield (Dirpath, Dirnames, Filenames)
64
65 # Check whether return type exists and in the first line
66 def FunctionLayoutCheckReturnType(self):
67 if EccGlobalData.gConfig.CFunctionLayoutCheckReturnType == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
68 EdkLogger.quiet("Checking function layout return type ...")
69
70 for Dirpath, Dirnames, Filenames in self.WalkTree():
71 for F in Filenames:
72 if os.path.splitext(F)[1] in ('.c', '.h'):
73 FullName = os.path.join(Dirpath, F)
74 c.CheckFuncLayoutReturnType(FullName)
75
76 # Check whether any optional functional modifiers exist and next to the return type
77 def FunctionLayoutCheckModifier(self):
78 if EccGlobalData.gConfig.CFunctionLayoutCheckOptionalFunctionalModifier == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
79 EdkLogger.quiet("Checking function layout modifier ...")
80
81 for Dirpath, Dirnames, Filenames in self.WalkTree():
82 for F in Filenames:
83 if os.path.splitext(F)[1] in ('.c', '.h'):
84 FullName = os.path.join(Dirpath, F)
85 c.CheckFuncLayoutModifier(FullName)
86
87 # Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list
88 # Check whether the closing parenthesis is on its own line and also indented two spaces
89 def FunctionLayoutCheckName(self):
90 if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionName == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
91 EdkLogger.quiet("Checking function layout function name ...")
92
93 for Dirpath, Dirnames, Filenames in self.WalkTree():
94 for F in Filenames:
95 if os.path.splitext(F)[1] in ('.c', '.h'):
96 FullName = os.path.join(Dirpath, F)
97 c.CheckFuncLayoutName(FullName)
98 # Check whether the function prototypes in include files have the same form as function definitions
99 def FunctionLayoutCheckPrototype(self):
100 if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionPrototype == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
101 EdkLogger.quiet("Checking function layout function prototype ...")
102
103 for Dirpath, Dirnames, Filenames in self.WalkTree():
104 for F in Filenames:
105 if os.path.splitext(F)[1] in ('.c'):
106 FullName = os.path.join(Dirpath, F)
107 EdkLogger.quiet("[PROTOTYPE]" + FullName)
108 c.CheckFuncLayoutPrototype(FullName)
109
110 # Check whether the body of a function is contained by open and close braces that must be in the first column
111 def FunctionLayoutCheckBody(self):
112 if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionBody == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
113 EdkLogger.quiet("Checking function layout function body ...")
114
115 for Dirpath, Dirnames, Filenames in self.WalkTree():
116 for F in Filenames:
117 if os.path.splitext(F)[1] in ('.c'):
118 FullName = os.path.join(Dirpath, F)
119 c.CheckFuncLayoutBody(FullName)
120
121 # Check whether the data declarations is the first code in a module.
122 # self.CFunctionLayoutCheckDataDeclaration = 1
123 # Check whether no initialization of a variable as part of its declaration
124 def FunctionLayoutCheckLocalVariable(self):
125 if EccGlobalData.gConfig.CFunctionLayoutCheckNoInitOfVariable == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
126 EdkLogger.quiet("Checking function layout local variables ...")
127
128 for Dirpath, Dirnames, Filenames in self.WalkTree():
129 for F in Filenames:
130 if os.path.splitext(F)[1] in ('.c'):
131 FullName = os.path.join(Dirpath, F)
132 c.CheckFuncLayoutLocalVariable(FullName)
133
134 # Check whether no use of STATIC for functions
135 # self.CFunctionLayoutCheckNoStatic = 1
136
137 # Declarations and Data Types Checking
138 def DeclAndDataTypeCheck(self):
139 self.DeclCheckNoUseCType()
140 self.DeclCheckInOutModifier()
141 self.DeclCheckEFIAPIModifier()
142 self.DeclCheckEnumeratedType()
143 self.DeclCheckStructureDeclaration()
144 self.DeclCheckSameStructure()
145 self.DeclCheckUnionType()
146
147
148 # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files.
149 def DeclCheckNoUseCType(self):
150 if EccGlobalData.gConfig.DeclarationDataTypeCheckNoUseCType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
151 EdkLogger.quiet("Checking Declaration No use C type ...")
152
153 for Dirpath, Dirnames, Filenames in self.WalkTree():
154 for F in Filenames:
155 if os.path.splitext(F)[1] in ('.h', '.c'):
156 FullName = os.path.join(Dirpath, F)
157 c.CheckDeclNoUseCType(FullName)
158
159 # 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
160 def DeclCheckInOutModifier(self):
161 if EccGlobalData.gConfig.DeclarationDataTypeCheckInOutModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
162 EdkLogger.quiet("Checking Declaration argument modifier ...")
163
164 for Dirpath, Dirnames, Filenames in self.WalkTree():
165 for F in Filenames:
166 if os.path.splitext(F)[1] in ('.h', '.c'):
167 FullName = os.path.join(Dirpath, F)
168 c.CheckDeclArgModifier(FullName)
169
170 # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols
171 def DeclCheckEFIAPIModifier(self):
172 if EccGlobalData.gConfig.DeclarationDataTypeCheckEFIAPIModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
173 pass
174
175 # Check whether Enumerated Type has a 'typedef' and the name is capital
176 def DeclCheckEnumeratedType(self):
177 if EccGlobalData.gConfig.DeclarationDataTypeCheckEnumeratedType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
178 EdkLogger.quiet("Checking Declaration enum typedef ...")
179
180 for Dirpath, Dirnames, Filenames in self.WalkTree():
181 for F in Filenames:
182 if os.path.splitext(F)[1] in ('.h', '.c'):
183 FullName = os.path.join(Dirpath, F)
184 EdkLogger.quiet("[ENUM]" + FullName)
185 c.CheckDeclEnumTypedef(FullName)
186
187 # Check whether Structure Type has a 'typedef' and the name is capital
188 def DeclCheckStructureDeclaration(self):
189 if EccGlobalData.gConfig.DeclarationDataTypeCheckStructureDeclaration == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
190 EdkLogger.quiet("Checking Declaration struct typedef ...")
191
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 EdkLogger.quiet("[STRUCT]" + FullName)
197 c.CheckDeclStructTypedef(FullName)
198
199 # Check whether having same Structure
200 def DeclCheckSameStructure(self):
201 if EccGlobalData.gConfig.DeclarationDataTypeCheckSameStructure == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
202 EdkLogger.quiet("Checking same struct ...")
203 AllStructure = {}
204 for IdentifierTable in EccGlobalData.gIdentifierTableList:
205 SqlCommand = """select ID, Name, BelongsToFile from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_STRUCTURE)
206 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
207 for Record in RecordSet:
208 if Record[1] != '':
209 if Record[1] not in AllStructure.keys():
210 AllStructure[Record[1]] = Record[2]
211 else:
212 ID = AllStructure[Record[1]]
213 SqlCommand = """select FullPath from File where ID = %s """ % ID
214 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
215 OtherMsg = "The structure name '%s' is duplicate" % Record[1]
216 if NewRecordSet != []:
217 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])
218 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, Record[1]):
219 EccGlobalData.gDb.TblReport.Insert(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, OtherMsg = OtherMsg, BelongsToTable = IdentifierTable, BelongsToItem = Record[0])
220
221 # Check whether Union Type has a 'typedef' and the name is capital
222 def DeclCheckUnionType(self):
223 if EccGlobalData.gConfig.DeclarationDataTypeCheckUnionType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
224 EdkLogger.quiet("Checking Declaration union typedef ...")
225
226 for Dirpath, Dirnames, Filenames in self.WalkTree():
227 for F in Filenames:
228 if os.path.splitext(F)[1] in ('.h', '.c'):
229 FullName = os.path.join(Dirpath, F)
230 EdkLogger.quiet("[UNION]" + FullName)
231 c.CheckDeclUnionTypedef(FullName)
232
233 # Predicate Expression Checking
234 def PredicateExpressionCheck(self):
235 self.PredicateExpressionCheckBooleanValue()
236 self.PredicateExpressionCheckNonBooleanOperator()
237 self.PredicateExpressionCheckComparisonNullType()
238
239 # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE
240 def PredicateExpressionCheckBooleanValue(self):
241 if EccGlobalData.gConfig.PredicateExpressionCheckBooleanValue == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
242 EdkLogger.quiet("Checking predicate expression Boolean value ...")
243
244 for Dirpath, Dirnames, Filenames in self.WalkTree():
245 for F in Filenames:
246 if os.path.splitext(F)[1] in ('.c'):
247 FullName = os.path.join(Dirpath, F)
248 EdkLogger.quiet("[BOOLEAN]" + FullName)
249 c.CheckBooleanValueComparison(FullName)
250
251 # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=).
252 def PredicateExpressionCheckNonBooleanOperator(self):
253 if EccGlobalData.gConfig.PredicateExpressionCheckNonBooleanOperator == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
254 EdkLogger.quiet("Checking predicate expression Non-Boolean variable...")
255
256 for Dirpath, Dirnames, Filenames in self.WalkTree():
257 for F in Filenames:
258 if os.path.splitext(F)[1] in ('.c'):
259 FullName = os.path.join(Dirpath, F)
260 EdkLogger.quiet("[NON-BOOLEAN]" + FullName)
261 c.CheckNonBooleanValueComparison(FullName)
262 # Check whether a comparison of any pointer to zero must be done via the NULL type
263 def PredicateExpressionCheckComparisonNullType(self):
264 if EccGlobalData.gConfig.PredicateExpressionCheckComparisonNullType == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
265 EdkLogger.quiet("Checking predicate expression NULL pointer ...")
266
267 for Dirpath, Dirnames, Filenames in self.WalkTree():
268 for F in Filenames:
269 if os.path.splitext(F)[1] in ('.c'):
270 FullName = os.path.join(Dirpath, F)
271 EdkLogger.quiet("[POINTER]" + FullName)
272 c.CheckPointerNullComparison(FullName)
273 # Include file checking
274 def IncludeFileCheck(self):
275 self.IncludeFileCheckIfndef()
276 self.IncludeFileCheckData()
277 self.IncludeFileCheckSameName()
278
279 # Check whether having include files with same name
280 def IncludeFileCheckSameName(self):
281 if EccGlobalData.gConfig.IncludeFileCheckSameName == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
282 EdkLogger.quiet("Checking same header file name ...")
283 SqlCommand = """select ID, FullPath from File
284 where Model = 1002 order by Name """
285 RecordDict = {}
286 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
287 for Record in RecordSet:
288 List = Record[1].replace('/', '\\').split('\\')
289 if len(List) >= 2:
290 Key = List[-2] + '\\' + List[-1]
291 else:
292 Key = List[0]
293 if Key not in RecordDict:
294 RecordDict[Key] = [Record]
295 else:
296 RecordDict[Key].append(Record)
297
298 for Key in RecordDict:
299 if len(RecordDict[Key]) > 1:
300 for Item in RecordDict[Key]:
301 Path = Item[1].replace(EccGlobalData.gWorkspace, '')
302 if Path.startswith('\\') or Path.startswith('/'):
303 Path = Path[1:]
304 if not EccGlobalData.gException.IsException(ERROR_INCLUDE_FILE_CHECK_NAME, Path):
305 EccGlobalData.gDb.TblReport.Insert(ERROR_INCLUDE_FILE_CHECK_NAME, OtherMsg = "The file name for [%s] is duplicate" % Path, BelongsToTable = 'File', BelongsToItem = Item[0])
306
307 # Check whether all include file contents is guarded by a #ifndef statement.
308 def IncludeFileCheckIfndef(self):
309 if EccGlobalData.gConfig.IncludeFileCheckIfndefStatement == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
310 EdkLogger.quiet("Checking header file ifndef ...")
311
312 for Dirpath, Dirnames, Filenames in self.WalkTree():
313 for F in Filenames:
314 if os.path.splitext(F)[1] in ('.h'):
315 FullName = os.path.join(Dirpath, F)
316 MsgList = c.CheckHeaderFileIfndef(FullName)
317
318 # Check whether include files NOT contain code or define data variables
319 def IncludeFileCheckData(self):
320 if EccGlobalData.gConfig.IncludeFileCheckData == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
321 EdkLogger.quiet("Checking header file data ...")
322
323 for Dirpath, Dirnames, Filenames in self.WalkTree():
324 for F in Filenames:
325 if os.path.splitext(F)[1] in ('.h'):
326 FullName = os.path.join(Dirpath, F)
327 MsgList = c.CheckHeaderFileData(FullName)
328
329 # Doxygen document checking
330 def DoxygenCheck(self):
331 self.DoxygenCheckFileHeader()
332 self.DoxygenCheckFunctionHeader()
333 self.DoxygenCheckCommentDescription()
334 self.DoxygenCheckCommentFormat()
335 self.DoxygenCheckCommand()
336
337 # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5
338 def DoxygenCheckFileHeader(self):
339 if EccGlobalData.gConfig.DoxygenCheckFileHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
340 EdkLogger.quiet("Checking Doxygen file header ...")
341
342 for Dirpath, Dirnames, Filenames in self.WalkTree():
343 for F in Filenames:
344 Ext = os.path.splitext(F)[1]
345 if Ext in ('.h', '.c'):
346 FullName = os.path.join(Dirpath, F)
347 MsgList = c.CheckFileHeaderDoxygenComments(FullName)
348 elif Ext in ('.inf', '.dec', '.dsc', '.fdf'):
349 FullName = os.path.join(Dirpath, F)
350 if not open(FullName).read().startswith('## @file'):
351 SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
352 ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
353 for Result in ResultSet:
354 Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file""'
355 EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
356
357
358 # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5
359 def DoxygenCheckFunctionHeader(self):
360 if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
361 EdkLogger.quiet("Checking Doxygen function header ...")
362
363 for Dirpath, Dirnames, Filenames in self.WalkTree():
364 for F in Filenames:
365 if os.path.splitext(F)[1] in ('.h', '.c'):
366 FullName = os.path.join(Dirpath, F)
367 MsgList = c.CheckFuncHeaderDoxygenComments(FullName)
368
369 # Check whether the first line of text in a comment block is a brief description of the element being documented.
370 # The brief description must end with a period.
371 def DoxygenCheckCommentDescription(self):
372 if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
373 pass
374
375 # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.
376 def DoxygenCheckCommentFormat(self):
377 if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
378 EdkLogger.quiet("Checking Doxygen comment ///< ...")
379
380 for Dirpath, Dirnames, Filenames in self.WalkTree():
381 for F in Filenames:
382 if os.path.splitext(F)[1] in ('.h', '.c'):
383 FullName = os.path.join(Dirpath, F)
384 MsgList = c.CheckDoxygenTripleForwardSlash(FullName)
385
386 # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.
387 def DoxygenCheckCommand(self):
388 if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
389 EdkLogger.quiet("Checking Doxygen command ...")
390
391 for Dirpath, Dirnames, Filenames in self.WalkTree():
392 for F in Filenames:
393 if os.path.splitext(F)[1] in ('.h', '.c'):
394 FullName = os.path.join(Dirpath, F)
395 MsgList = c.CheckDoxygenCommand(FullName)
396
397 # Meta-Data File Processing Checking
398 def MetaDataFileCheck(self):
399 self.MetaDataFileCheckPathName()
400 self.MetaDataFileCheckGenerateFileList()
401 self.MetaDataFileCheckLibraryInstance()
402 self.MetaDataFileCheckLibraryInstanceDependent()
403 self.MetaDataFileCheckLibraryInstanceOrder()
404 self.MetaDataFileCheckLibraryNoUse()
405 self.MetaDataFileCheckBinaryInfInFdf()
406 self.MetaDataFileCheckPcdDuplicate()
407 self.MetaDataFileCheckPcdFlash()
408 self.MetaDataFileCheckPcdNoUse()
409 self.MetaDataFileCheckGuidDuplicate()
410 self.MetaDataFileCheckModuleFileNoUse()
411 self.MetaDataFileCheckPcdType()
412 self.MetaDataFileCheckModuleFileGuidDuplication()
413
414 # Check whether each file defined in meta-data exists
415 def MetaDataFileCheckPathName(self):
416 if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
417 # This item is covered when parsing Inf/Dec/Dsc files
418 pass
419
420 # Generate a list for all files defined in meta-data files
421 def MetaDataFileCheckGenerateFileList(self):
422 if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
423 # This item is covered when parsing Inf/Dec/Dsc files
424 pass
425
426 # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.
427 # Each Library Instance must specify the Supported Module Types in its Inf file,
428 # and any module specifying the library instance must be one of the supported types.
429 def MetaDataFileCheckLibraryInstance(self):
430 if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
431 EdkLogger.quiet("Checking for library instance type issue ...")
432 SqlCommand = """select A.ID, A.Value2, B.Value2 from Inf as A left join Inf as B
433 where A.Value1 = 'LIBRARY_CLASS' and A.Model = %s
434 and B.Value1 = 'MODULE_TYPE' and B.Model = %s and A.BelongsToFile = B.BelongsToFile
435 group by A.BelongsToFile""" % (MODEL_META_DATA_HEADER, MODEL_META_DATA_HEADER)
436 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
437 LibraryClasses = {}
438 for Record in RecordSet:
439 List = Record[1].split('|', 1)
440 SupModType = []
441 if len(List) == 1:
442 SupModType = SUP_MODULE_LIST_STRING.split(TAB_VALUE_SPLIT)
443 elif len(List) == 2:
444 SupModType = List[1].split()
445
446 if List[0] not in LibraryClasses:
447 LibraryClasses[List[0]] = SupModType
448 else:
449 for Item in SupModType:
450 if Item not in LibraryClasses[List[0]]:
451 LibraryClasses[List[0]].append(Item)
452
453 if Record[2] != 'BASE' and Record[2] not in SupModType:
454 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])
455
456 SqlCommand = """select A.ID, A.Value1, B.Value2 from Inf as A left join Inf as B
457 where A.Model = %s and B.Value1 = '%s' and B.Model = %s
458 and B.BelongsToFile = A.BelongsToFile""" \
459 % (MODEL_EFI_LIBRARY_CLASS, 'MODULE_TYPE', MODEL_META_DATA_HEADER)
460 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
461 # Merge all LibraryClasses' supmodlist
462 RecordDict = {}
463 for Record in RecordSet:
464 if Record[1] not in RecordDict:
465 RecordDict[Record[1]] = [str(Record[2])]
466 else:
467 if Record[2] not in RecordDict[Record[1]]:
468 RecordDict[Record[1]].append(Record[2])
469
470 for Record in RecordSet:
471 if Record[1] in LibraryClasses:
472 if Record[2] not in LibraryClasses[Record[1]] and 'BASE' not in RecordDict[Record[1]]:
473 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):
474 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])
475 else:
476 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):
477 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])
478
479 # Check whether a Library Instance has been defined for all dependent library classes
480 def MetaDataFileCheckLibraryInstanceDependent(self):
481 if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
482 EdkLogger.quiet("Checking for library instance dependent issue ...")
483 SqlCommand = """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS
484 LibraryClasses = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
485 for LibraryClass in LibraryClasses:
486 if LibraryClass[1].upper() != 'NULL':
487 LibraryIns = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, LibraryClass[2]))
488 SqlCommand = """select Value2 from Inf where BelongsToFile =
489 (select ID from File where lower(FullPath) = lower('%s'))
490 and Value1 = '%s'""" % (LibraryIns, 'LIBRARY_CLASS')
491 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
492 IsFound = False
493 for Record in RecordSet:
494 LibName = Record[0].split('|', 1)[0]
495 if LibraryClass[1] == LibName:
496 IsFound = True
497 if not IsFound:
498 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, LibraryClass[1]):
499 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])
500
501 # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies
502 def MetaDataFileCheckLibraryInstanceOrder(self):
503 if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
504 # This checkpoint is not necessary for Ecc check
505 pass
506
507 # Check whether the unnecessary inclusion of library classes in the Inf file
508 def MetaDataFileCheckLibraryNoUse(self):
509 if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
510 EdkLogger.quiet("Checking for library instance not used ...")
511 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)
512 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
513 for Record in RecordSet:
514 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, Record[1]):
515 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])
516
517 # 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
518 def MetaDataFileCheckBinaryInfInFdf(self):
519 if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
520 EdkLogger.quiet("Checking for non-binary modules defined in FDF files ...")
521 SqlCommand = """select A.ID, A.Value1 from Fdf as A
522 where A.Model = %s
523 and A.Enabled > -1
524 and A.Value1 not in
525 (select B.Value1 from Dsc as B
526 where B.Model = %s
527 and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT)
528 RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)
529 for Record in RecordSet:
530 FdfID = Record[0]
531 FilePath = Record[1]
532 FilePath = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, FilePath))
533 SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')
534 """ % (MODEL_EFI_SOURCE_FILE, FilePath)
535 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
536 if NewRecordSet!= []:
537 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, FilePath):
538 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)
539
540 # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.
541 def MetaDataFileCheckPcdDuplicate(self):
542 if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
543 EdkLogger.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...")
544 SqlCommand = """
545 select A.ID, A.Value2, A.BelongsToFile, B.ID, B.Value2, B.BelongsToFile from Dsc as A, Fdf as B
546 where A.Model >= %s and A.Model < %s
547 and B.Model >= %s and B.Model < %s
548 and A.Value2 = B.Value2
549 and A.Enabled > -1
550 and B.Enabled > -1
551 group by A.ID
552 """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)
553 RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
554 for Record in RecordSet:
555 SqlCommand1 = """select Name from File where ID = %s""" %Record[2]
556 SqlCommand2 = """select Name from File where ID = %s""" %Record[5]
557 DscFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand1)[0][0])[0]
558 FdfFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand2)[0][0])[0]
559 print DscFileName, 111, FdfFileName
560 if DscFileName != FdfFileName:
561 continue
562 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]):
563 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])
564 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[3]):
565 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])
566
567 EdkLogger.quiet("Checking for duplicate PCDs defined in DEC files ...")
568 SqlCommand = """
569 select A.ID, A.Value2 from Dec as A, Dec as B
570 where A.Model >= %s and A.Model < %s
571 and B.Model >= %s and B.Model < %s
572 and A.Value2 = B.Value2
573 and ((A.Arch = B.Arch) and (A.Arch != 'COMMON' or B.Arch != 'COMMON'))
574 and A.ID != B.ID
575 and A.Enabled > -1
576 and B.Enabled > -1
577 and A.BelongsToFile = B.BelongsToFile
578 group by A.ID
579 """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)
580 RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
581 for Record in RecordSet:
582 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]):
583 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])
584
585 # Check whether PCD settings in the FDF file can only be related to flash.
586 def MetaDataFileCheckPcdFlash(self):
587 if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
588 EdkLogger.quiet("Checking only Flash related PCDs are used in FDF ...")
589 SqlCommand = """
590 select ID, Value2, BelongsToFile from Fdf as A
591 where A.Model >= %s and Model < %s
592 and A.Enabled > -1
593 and A.Value2 not like '%%Flash%%'
594 """% (MODEL_PCD, MODEL_META_DATA_HEADER)
595 RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)
596 for Record in RecordSet:
597 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, Record[1]):
598 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])
599
600 # Check whether PCDs used in Inf files but not specified in Dsc or FDF files
601 def MetaDataFileCheckPcdNoUse(self):
602 if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
603 EdkLogger.quiet("Checking for non-specified PCDs ...")
604 SqlCommand = """
605 select ID, Value2, BelongsToFile from Inf as A
606 where A.Model >= %s and Model < %s
607 and A.Enabled > -1
608 and A.Value2 not in
609 (select Value2 from Dsc as B
610 where B.Model >= %s and B.Model < %s
611 and B.Enabled > -1)
612 and A.Value2 not in
613 (select Value2 from Fdf as C
614 where C.Model >= %s and C.Model < %s
615 and C.Enabled > -1)
616 """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)
617 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
618 for Record in RecordSet:
619 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, Record[1]):
620 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])
621
622 # Check whether having duplicate guids defined for Guid/Protocol/Ppi
623 def MetaDataFileCheckGuidDuplicate(self):
624 if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
625 EdkLogger.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...")
626 # Check Guid
627 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec)
628 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc)
629 self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID)
630 # Check protocol
631 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec)
632 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc)
633 self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL)
634 # Check ppi
635 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec)
636 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc)
637 self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI)
638
639 # Check whether all files under module directory are described in INF files
640 def MetaDataFileCheckModuleFileNoUse(self):
641 if EccGlobalData.gConfig.MetaDataFileCheckModuleFileNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
642 EdkLogger.quiet("Checking for no used module files ...")
643 SqlCommand = """
644 select upper(Path) from File where ID in (select BelongsToFile from INF where BelongsToFile != -1)
645 """
646 InfPathSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
647 InfPathList = []
648 for Item in InfPathSet:
649 if Item[0] not in InfPathList:
650 InfPathList.append(Item[0])
651 SqlCommand = """
652 select ID, Path, FullPath from File where upper(FullPath) not in
653 (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B
654 where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and
655 B.BelongsToFile = A.ID and B.Model = %s)
656 and (Model = %s or Model = %s)
657 """ % (MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H)
658 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
659 for Record in RecordSet:
660 Path = Record[1]
661 Path = Path.upper().replace('\X64', '').replace('\IA32', '').replace('\EBC', '').replace('\IPF', '').replace('\ARM', '')
662 if Path in InfPathList:
663 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, Record[2]):
664 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])
665
666 # Check whether the PCD is correctly used in C function via its type
667 def MetaDataFileCheckPcdType(self):
668 if EccGlobalData.gConfig.MetaDataFileCheckPcdType == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
669 EdkLogger.quiet("Checking for pcd type in c code function usage ...")
670 SqlCommand = """
671 select ID, Model, Value1, BelongsToFile from INF where Model > %s and Model < %s
672 """ % (MODEL_PCD, MODEL_META_DATA_HEADER)
673 PcdSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
674 for Pcd in PcdSet:
675 Model = Pcd[1]
676 PcdName = Pcd[2]
677 if len(Pcd[2].split(".")) > 1:
678 PcdName = Pcd[2].split(".")[1]
679 BelongsToFile = Pcd[3]
680 SqlCommand = """
681 select ID from File where FullPath in
682 (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s
683 and B.ID = %s)
684 """ %(MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile)
685 TableSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
686 for Tbl in TableSet:
687 TblName = 'Identifier' + str(Tbl[0])
688 SqlCommand = """
689 select Name, ID from %s where value like '%s' and Model = %s
690 """ % (TblName, PcdName, MODEL_IDENTIFIER_FUNCTION_CALLING)
691 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
692 TblNumber = TblName.replace('Identifier', '')
693 for Record in RecordSet:
694 FunName = Record[0]
695 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, FunName):
696 if Model in [MODEL_PCD_FIXED_AT_BUILD] and not FunName.startswith('FixedPcdGet'):
697 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])
698 if Model in [MODEL_PCD_FEATURE_FLAG] and (not FunName.startswith('FeaturePcdGet') and not FunName.startswith('FeaturePcdSet')):
699 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])
700 if Model in [MODEL_PCD_PATCHABLE_IN_MODULE] and (not FunName.startswith('PatchablePcdGet') and not FunName.startswith('PatchablePcdSet')):
701 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])
702
703 #ERROR_META_DATA_FILE_CHECK_PCD_TYPE
704 pass
705
706 # Internal worker function to get the INF workspace relative path from FileID
707 def GetInfFilePathFromID(self, FileID):
708 Table = EccGlobalData.gDb.TblFile
709 SqlCommand = """select A.FullPath from %s as A where A.ID = %s""" % (Table.Table, FileID)
710 RecordSet = Table.Exec(SqlCommand)
711 Path = ""
712 for Record in RecordSet:
713 Path = Record[0].replace(EccGlobalData.gWorkspace, '')
714 if Path.startswith('\\') or Path.startswith('/'):
715 Path = Path[1:]
716 return Path
717
718 # Check whether two module INFs under one workspace has the same FILE_GUID value
719 def MetaDataFileCheckModuleFileGuidDuplication(self):
720 if EccGlobalData.gConfig.MetaDataFileCheckModuleFileGuidDuplication == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
721 EdkLogger.quiet("Checking for pcd type in c code function usage ...")
722 Table = EccGlobalData.gDb.TblInf
723 SqlCommand = """
724 select A.ID, A.Value2, A.BelongsToFile, B.BelongsToFile from %s as A, %s as B
725 where A.Value1 = 'FILE_GUID' and B.Value1 = 'FILE_GUID' and
726 A.Value2 = B.Value2 and A.ID <> B.ID group by A.ID
727 """ % (Table.Table, Table.Table)
728 RecordSet = Table.Exec(SqlCommand)
729 for Record in RecordSet:
730 InfPath1 = self.GetInfFilePathFromID(Record[2])
731 InfPath2 = self.GetInfFilePathFromID(Record[3])
732 if InfPath1 and InfPath2:
733 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION, InfPath1):
734 Msg = "The FILE_GUID of INF file [%s] is duplicated with that of %s" % (InfPath1, InfPath2)
735 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION, OtherMsg = Msg, BelongsToTable = Table.Table, BelongsToItem = Record[0])
736
737
738 # Check whether these is duplicate Guid/Ppi/Protocol name
739 def CheckGuidProtocolPpi(self, ErrorID, Model, Table):
740 Name = ''
741 if Model == MODEL_EFI_GUID:
742 Name = 'guid'
743 if Model == MODEL_EFI_PROTOCOL:
744 Name = 'protocol'
745 if Model == MODEL_EFI_PPI:
746 Name = 'ppi'
747 SqlCommand = """
748 select A.ID, A.Value1 from %s as A, %s as B
749 where A.Model = %s and B.Model = %s
750 and A.Value1 = B.Value1 and A.ID <> B.ID
751 and A.Enabled > -1
752 and B.Enabled > -1
753 group by A.ID
754 """ % (Table.Table, Table.Table, Model, Model)
755 RecordSet = Table.Exec(SqlCommand)
756 for Record in RecordSet:
757 if not EccGlobalData.gException.IsException(ErrorID, Record[1]):
758 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])
759
760 # Check whether these is duplicate Guid/Ppi/Protocol value
761 def CheckGuidProtocolPpiValue(self, ErrorID, Model):
762 Name = ''
763 Table = EccGlobalData.gDb.TblDec
764 if Model == MODEL_EFI_GUID:
765 Name = 'guid'
766 if Model == MODEL_EFI_PROTOCOL:
767 Name = 'protocol'
768 if Model == MODEL_EFI_PPI:
769 Name = 'ppi'
770 SqlCommand = """
771 select A.ID, A.Value2 from %s as A, %s as B
772 where A.Model = %s and B.Model = %s
773 and A.Value2 = B.Value2 and A.ID <> B.ID
774 group by A.ID
775 """ % (Table.Table, Table.Table, Model, Model)
776 RecordSet = Table.Exec(SqlCommand)
777 for Record in RecordSet:
778 if not EccGlobalData.gException.IsException(ErrorID, Record[1]):
779 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])
780
781 # Naming Convention Check
782 def NamingConventionCheck(self):
783 if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' \
784 or EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' \
785 or EccGlobalData.gConfig.NamingConventionCheckIfndefStatement == '1' \
786 or EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' \
787 or EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' \
788 or EccGlobalData.gConfig.NamingConventionCheckAll == '1'\
789 or EccGlobalData.gConfig.CheckAll == '1':
790 for Dirpath, Dirnames, Filenames in self.WalkTree():
791 for F in Filenames:
792 if os.path.splitext(F)[1] in ('.h', '.c'):
793 FullName = os.path.join(Dirpath, F)
794 Id = c.GetTableID(FullName)
795 if Id < 0:
796 continue
797 FileTable = 'Identifier' + str(Id)
798 self.NamingConventionCheckDefineStatement(FileTable)
799 self.NamingConventionCheckTypedefStatement(FileTable)
800 self.NamingConventionCheckIfndefStatement(FileTable)
801 self.NamingConventionCheckVariableName(FileTable)
802 self.NamingConventionCheckSingleCharacterVariable(FileTable)
803
804 self.NamingConventionCheckPathName()
805 self.NamingConventionCheckFunctionName()
806
807 # Check whether only capital letters are used for #define declarations
808 def NamingConventionCheckDefineStatement(self, FileTable):
809 if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
810 EdkLogger.quiet("Checking naming covention of #define statement ...")
811
812 SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_DEFINE)
813 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
814 for Record in RecordSet:
815 Name = Record[1].strip().split()[1]
816 if Name.find('(') != -1:
817 Name = Name[0:Name.find('(')]
818 if Name.upper() != Name:
819 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, Name):
820 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])
821
822 # Check whether only capital letters are used for typedef declarations
823 def NamingConventionCheckTypedefStatement(self, FileTable):
824 if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
825 EdkLogger.quiet("Checking naming covention of #typedef statement ...")
826
827 SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_TYPEDEF)
828 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
829 for Record in RecordSet:
830 Name = Record[1].strip()
831 if Name != '' and Name != None:
832 if Name[0] == '(':
833 Name = Name[1:Name.find(')')]
834 if Name.find('(') > -1:
835 Name = Name[Name.find('(') + 1 : Name.find(')')]
836 Name = Name.replace('WINAPI', '')
837 Name = Name.replace('*', '').strip()
838 if Name.upper() != Name:
839 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, Name):
840 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])
841
842 # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'.
843 def NamingConventionCheckIfndefStatement(self, FileTable):
844 if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
845 EdkLogger.quiet("Checking naming covention of #ifndef statement ...")
846
847 SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_IFNDEF)
848 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
849 for Record in RecordSet:
850 Name = Record[1].replace('#ifndef', '').strip()
851 if Name[0] != '_' or Name[-1] != '_':
852 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, Name):
853 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])
854
855 # Rule for path name, variable name and function name
856 # 1. First character should be upper case
857 # 2. Existing lower case in a word
858 # 3. No space existence
859 # Check whether the path name followed the rule
860 def NamingConventionCheckPathName(self):
861 if EccGlobalData.gConfig.NamingConventionCheckPathName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
862 EdkLogger.quiet("Checking naming covention of file path name ...")
863 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
864 SqlCommand = """select ID, Name from File"""
865 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
866 for Record in RecordSet:
867 if not Pattern.match(Record[1]):
868 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, Record[1]):
869 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])
870
871 # Rule for path name, variable name and function name
872 # 1. First character should be upper case
873 # 2. Existing lower case in a word
874 # 3. No space existence
875 # 4. Global variable name must start with a 'g'
876 # Check whether the variable name followed the rule
877 def NamingConventionCheckVariableName(self, FileTable):
878 if EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
879 EdkLogger.quiet("Checking naming covention of variable name ...")
880 Pattern = re.compile(r'^[A-Zgm]+\S*[a-z]\S*$')
881
882 SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE)
883 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
884 for Record in RecordSet:
885 if not Pattern.match(Record[1]):
886 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Record[1]):
887 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])
888
889 # Rule for path name, variable name and function name
890 # 1. First character should be upper case
891 # 2. Existing lower case in a word
892 # 3. No space existence
893 # Check whether the function name followed the rule
894 def NamingConventionCheckFunctionName(self):
895 if EccGlobalData.gConfig.NamingConventionCheckFunctionName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
896 EdkLogger.quiet("Checking naming covention of function name ...")
897 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
898 SqlCommand = """select ID, Name from Function"""
899 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
900 for Record in RecordSet:
901 if not Pattern.match(Record[1]):
902 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, Record[1]):
903 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])
904
905 # Check whether NO use short variable name with single character
906 def NamingConventionCheckSingleCharacterVariable(self, FileTable):
907 if EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
908 EdkLogger.quiet("Checking naming covention of single character variable name ...")
909
910 SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE)
911 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
912 for Record in RecordSet:
913 Variable = Record[1].replace('*', '')
914 if len(Variable) == 1:
915 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, Record[1]):
916 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])
917
918 ##
919 #
920 # This acts like the main() function for the script, unless it is 'import'ed into another
921 # script.
922 #
923 if __name__ == '__main__':
924 Check = Check()
925 Check.Check()