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