1. Add an option to keep old database when start ecc tool
[people/mcb30/basetools.git] / Source / Python / Ecc / Check.py
1 ## @file\r
2 # This file is used to define checkpoints used by ECC tool\r
3 #\r
4 # Copyright (c) 2008, Intel Corporation\r
5 # All rights reserved. This program and the accompanying materials\r
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
13 import os\r
14 import re\r
15 from CommonDataClass.DataClass import *\r
16 from EccToolError import *\r
17 import EccGlobalData\r
18 import c\r
19 \r
20 ## Check\r
21 #\r
22 # This class is to define checkpoints used by ECC tool\r
23 #\r
24 # @param object:          Inherited from object class\r
25 #\r
26 class Check(object):\r
27     def __init__(self):\r
28         pass\r
29      \r
30     #\r
31     # Check all required checkpoints\r
32     #   \r
33     def Check(self):\r
34         self.MetaDataFileCheck()\r
35         self.DoxygenCheck()\r
36     \r
37     #\r
38     # Doxygen document checking\r
39     #\r
40     def DoxygenCheck(self):\r
41         self.DoxygenCheckFileHeader()\r
42         self.DoxygenCheckFunctionHeader()\r
43         self.DoxygenCheckCommentDescription()\r
44         self.DoxygenCheckCommentFormat()\r
45         self.DoxygenCheckCommand()\r
46     \r
47     #\r
48     # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5\r
49     #\r
50     def DoxygenCheckFileHeader(self):\r
51         if EccGlobalData.gConfig.DoxygenCheckFileHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
52             pass\r
53     \r
54     #\r
55     # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5\r
56     #\r
57     def DoxygenCheckFunctionHeader(self):\r
58         if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
59             Tuple = os.walk(EccGlobalData.gTarget)\r
60             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
61 #            ParseErrorFileList = []\r
62         \r
63             for Dirpath, Dirnames, Filenames in Tuple:\r
64                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
65                     continue\r
66                 for F in Filenames:\r
67                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
68                         FullName = os.path.join(Dirpath, F)\r
69                         MsgList = c.CheckFuncHeaderDoxygenComments(FullName)\r
70                         for Msg in MsgList:\r
71                             print Msg\r
72             print 'Done'                \r
73                             \r
74     #\r
75     # Check whether the first line of text in a comment block is a brief description of the element being documented. \r
76     # The brief description must end with a period.\r
77     #\r
78     def DoxygenCheckCommentDescription(self):\r
79         if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
80             pass\r
81 \r
82     #\r
83     # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.\r
84     #\r
85     def DoxygenCheckCommentFormat(self):\r
86         if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
87             pass\r
88         \r
89     #\r
90     # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.\r
91     #\r
92     def DoxygenCheckCommand(self):\r
93         if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
94             pass\r
95     \r
96     #\r
97     # Meta-Data File Processing Checking\r
98     #\r
99     def MetaDataFileCheck(self):\r
100         self.MetaDataFileCheckPathName()\r
101         self.MetaDataFileCheckGenerateFileList()\r
102         self.MetaDataFileCheckLibraryInstance()\r
103         self.MetaDataFileCheckLibraryInstanceDependent()\r
104         self.MetaDataFileCheckLibraryInstanceOrder()\r
105         self.MetaDataFileCheckLibraryNoUse()\r
106         self.MetaDataFileCheckBinaryInfInFdf()\r
107         self.MetaDataFileCheckPcdDuplicate()\r
108         self.MetaDataFileCheckPcdFlash()\r
109         self.MetaDataFileCheckPcdNoUse()\r
110         self.MetaDataFileCheckGuidDuplicate()\r
111 \r
112     #\r
113     # Check whether each file defined in meta-data exists\r
114     #\r
115     def MetaDataFileCheckPathName(self):\r
116         if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
117             # This item is covered when parsing Inf/Dec/Dsc files\r
118             pass\r
119     \r
120     #\r
121     # Generate a list for all files defined in meta-data files\r
122     #\r
123     def MetaDataFileCheckGenerateFileList(self):\r
124         if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
125             # This item is covered when parsing Inf/Dec/Dsc files\r
126             pass\r
127     \r
128     #\r
129     # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.  \r
130     # Each Library Instance must specify the Supported Module Types in its Inf file, \r
131     # and any module specifying the library instance must be one of the supported types.\r
132     #\r
133     def MetaDataFileCheckLibraryInstance(self):\r
134         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
135             pass\r
136 \r
137     #\r
138     # Check whether a Library Instance has been defined for all dependent library classes\r
139     #\r
140     def MetaDataFileCheckLibraryInstanceDependent(self):\r
141         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
142             pass\r
143 \r
144     #\r
145     # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies\r
146     #\r
147     def MetaDataFileCheckLibraryInstanceOrder(self):\r
148         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
149             pass\r
150 \r
151     #\r
152     # Check whether the unnecessary inclusion of library classes in the Inf file\r
153     #\r
154     def MetaDataFileCheckLibraryNoUse(self):\r
155         if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
156             pass\r
157 \r
158     #\r
159     # 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
160     #\r
161     def MetaDataFileCheckBinaryInfInFdf(self):\r
162         if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
163             SqlCommand = """select A.ID, A.Value1 from Fdf as A\r
164                          where A.Model = %s\r
165                          and A.Enabled > -1\r
166                          and A.Value1 not in \r
167                          (select B.Value1 from Dsc as B\r
168                          where B.Model = %s\r
169                          and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT)\r
170             RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
171             for Record in RecordSet:\r
172                 FdfID = Record[0]\r
173                 FilePath = Record[1]\r
174                 FilePath = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, FilePath))\r
175                 SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')\r
176                                 """ % (MODEL_EFI_SOURCE_FILE, FilePath)\r
177                 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
178                 if NewRecordSet!= []:\r
179                     EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, OtherMsg = "File %s defined in Fdf file but not in Dsc file should be a binary module" % (FilePath), BelongsToTable = 'Fdf', BelongsToItem = FdfID)\r
180 \r
181     #\r
182     # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.\r
183     #\r
184     def MetaDataFileCheckPcdDuplicate(self):\r
185         if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
186             EdkLogger.quiet("Checking duplicate pcd defined in both Dsc and Fdf files ...")\r
187             SqlCommand = """\r
188                          select A.ID, A.Value2, B.ID, B.Value2 from Dsc as A, Fdf as B \r
189                          where A.Model >= %s and A.Model < %s \r
190                          and B.Model >= %s and B.Model < %s \r
191                          and A.Value2 = B.Value2\r
192                          and A.Enabled > -1\r
193                          and B.Enabled > -1\r
194                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
195             RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
196             for Record in RecordSet:\r
197                 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]), BelongsToTable = 'Dsc', BelongsToItem = Record[0])\r
198                 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[3]), BelongsToTable = 'Fdf', BelongsToItem = Record[2])\r
199 \r
200     #\r
201     # Check whether PCD settings in the FDF file can only be related to flash.\r
202     #\r
203     def MetaDataFileCheckPcdFlash(self):\r
204         if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
205             EdkLogger.quiet("Checking only Flash related Pcd is used in FDF ...")\r
206             SqlCommand = """\r
207                          select ID, Value2, BelongsToFile from Fdf as A\r
208                          where A.Model >= %s and Model < %s\r
209                          and A.Enabled > -1\r
210                          and A.Value2 not like '%%Flash%%'\r
211                          """% (MODEL_PCD, MODEL_META_DATA_HEADER)\r
212             RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
213             for Record in RecordSet:\r
214                 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]), BelongsToTable = 'Fdf', BelongsToItem = Record[0])\r
215         \r
216     #\r
217     # Check whether PCDs used in Inf files but not specified in Dsc or FDF files\r
218     #\r
219     def MetaDataFileCheckPcdNoUse(self):\r
220         if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
221             EdkLogger.quiet("Checking no use pcds ...")\r
222             SqlCommand = """\r
223                          select ID, Value2, BelongsToFile from Inf as A \r
224                          where A.Model >= %s and Model < %s\r
225                          and A.Enabled > -1\r
226                          and A.Value2 not in \r
227                              (select Value2 from Dsc as B \r
228                               where B.Model >= %s and B.Model < %s\r
229                               and B.Enabled > -1)\r
230                          and A.Value2 not in\r
231                              (select Value2 from Fdf as C \r
232                               where C.Model >= %s and C.Model < %s\r
233                               and C.Enabled > -1)\r
234                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
235             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
236             for Record in RecordSet:\r
237                 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, OtherMsg = "The pcd '%s' defined in Inf file is not referenced by any Dsc of Fdf files" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0])\r
238         \r
239     #\r
240     # Check whether having duplicate guids defined for Guid/Protocol/Ppi\r
241     #\r
242     def MetaDataFileCheckGuidDuplicate(self):\r
243         if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
244             EdkLogger.quiet("Checking duplicate guid/ppi/protocol ...")\r
245             #\r
246             # Check Guid\r
247             #\r
248             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec)\r
249             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc)\r
250             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID)\r
251             #\r
252             # Check protocol\r
253             #\r
254             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec)\r
255             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc)\r
256             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL)\r
257             #\r
258             # Check ppi\r
259             #\r
260             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec)\r
261             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc)\r
262             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI)\r
263 \r
264             #EdkLogger.quiet("Checking duplicate guid/ppi/protocol done!")\r
265     \r
266     #\r
267     # Check whether these is duplicate Guid/Ppi/Protocol name\r
268     #\r
269     def CheckGuidProtocolPpi(self, ErrorID, Model, Table):\r
270         Name = ''\r
271         if Model == MODEL_EFI_GUID:\r
272             Name = 'guid'\r
273         if Model == MODEL_EFI_PROTOCOL:\r
274             Name = 'protocol'\r
275         if Model == MODEL_EFI_PPI:\r
276             Name = 'ppi'\r
277         SqlCommand = """\r
278                      select A.ID, A.Value1 from %s as A, %s as B \r
279                      where A.Model = %s and B.Model = %s \r
280                      and A.Value1 = B.Value1 and A.ID <> B.ID \r
281                      and A.Enabled > -1\r
282                      and B.Enabled > -1\r
283                      group by A.ID\r
284                      """ % (Table.Table, Table.Table, Model, Model)\r
285         RecordSet = Table.Exec(SqlCommand)\r
286         for Record in RecordSet:\r
287             EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg = "The %s name '%s' is defined more than one time" % (Name, Record[1]), BelongsToTable = Table.Table, BelongsToItem = Record[0])\r
288 \r
289     #\r
290     # Check whether these is duplicate Guid/Ppi/Protocol value\r
291     #\r
292     def CheckGuidProtocolPpiValue(self, ErrorID, Model):\r
293         Name = ''\r
294         Table = EccGlobalData.gDb.TblDec\r
295         if Model == MODEL_EFI_GUID:\r
296             Name = 'guid'\r
297         if Model == MODEL_EFI_PROTOCOL:\r
298             Name = 'protocol'\r
299         if Model == MODEL_EFI_PPI:\r
300             Name = 'ppi'\r
301         SqlCommand = """\r
302                      select A.ID, A.Value2 from %s as A, %s as B \r
303                      where A.Model = %s and B.Model = %s \r
304                      and A.Value2 = B.Value2 and A.ID <> B.ID \r
305                      group by A.ID\r
306                      """ % (Table.Table, Table.Table, Model, Model)\r
307         RecordSet = Table.Exec(SqlCommand)\r
308         for Record in RecordSet:\r
309             EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg = "The %s value '%s' is used more than one time" % (Name, Record[1]), BelongsToTable = Table.Table, BelongsToItem = Record[0])\r
310 \r
311 ##\r
312 #\r
313 # This acts like the main() function for the script, unless it is 'import'ed into another\r
314 # script.\r
315 #\r
316 if __name__ == '__main__':\r
317     Check = Check()\r
318     Check.Check()