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