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