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