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