824984129ad0f2f7cfa7f2a08d0324274d8355b8
[efi/basetools/.git] / Source / Python / Eot / Report.py
1 ## @file\r
2 # This file is used to create report for Eot tool\r
3 #\r
4 # Copyright (c) 2008 - 2010, 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 \r
14 ##\r
15 # Import Modules\r
16 #\r
17 import os\r
18 import EotGlobalData\r
19 \r
20 ## Report() class\r
21 #\r
22 #  This class defined Report\r
23 #\r
24 #  @param object: Inherited from object class\r
25 #\r
26 class Report(object):\r
27     ## The constructor\r
28     #\r
29     #  @param  self: The object pointer\r
30     #  @param  ReportName: name of the report\r
31     #  @param  FvObj: FV object after parsing FV images\r
32     #\r
33     def __init__(self, ReportName = 'Report.html', FvObj = None):\r
34         self.ReportName = ReportName\r
35         self.Op = open(ReportName, 'w+')\r
36         self.FvObj = FvObj\r
37         self.FfsIndex = 0\r
38         self.PpiIndex = 0\r
39         self.ProtocolIndex = 0\r
40         if EotGlobalData.gMACRO['EFI_SOURCE'] == '':\r
41             EotGlobalData.gMACRO['EFI_SOURCE'] = EotGlobalData.gMACRO['EDK_SOURCE']\r
42 \r
43     ## WriteLn() method\r
44     #\r
45     #  Write a line in the report\r
46     #\r
47     #  @param  self: The object pointer\r
48     #  @param Line:  The lint to be written into\r
49     #\r
50     def WriteLn(self, Line):\r
51         self.Op.write('%s\n' % Line)\r
52 \r
53     ## GenerateReport() method\r
54     #\r
55     #  A caller to generate report\r
56     #\r
57     #  @param  self: The object pointer\r
58     #\r
59     def GenerateReport(self):\r
60         self.GenerateHeader()\r
61         self.GenerateFv()\r
62         self.GenerateTail()\r
63         self.Op.close()\r
64         self.GenerateUnDispatchedList()\r
65 \r
66     ## GenerateUnDispatchedList() method\r
67     #\r
68     #  Create a list for not dispatched items\r
69     #\r
70     #  @param  self: The object pointer\r
71     #\r
72     def GenerateUnDispatchedList(self):\r
73         FvObj = self.FvObj\r
74         EotGlobalData.gOP_UN_DISPATCHED.write('%s\n' % FvObj.Name)\r
75         for Item in FvObj.UnDispatchedFfsDict:\r
76             EotGlobalData.gOP_UN_DISPATCHED.write('%s\n' % FvObj.UnDispatchedFfsDict[Item])\r
77 \r
78     ## GenerateFv() method\r
79     #\r
80     #  Generate FV information\r
81     #\r
82     #  @param  self: The object pointer\r
83     #\r
84     def GenerateFv(self):\r
85         FvObj = self.FvObj\r
86         Content = """  <tr>\r
87     <td width="20%%"><strong>Name</strong></td>\r
88     <td width="60%%"><strong>Guid</strong></td>\r
89     <td width="20%%"><strong>Size</strong></td>\r
90   </tr>"""\r
91         self.WriteLn(Content)\r
92 \r
93         for Info in FvObj.BasicInfo:\r
94             FvName = Info[0]\r
95             FvGuid = Info[1]\r
96             FvSize = Info[2]\r
97 \r
98             Content = """  <tr>\r
99     <td>%s</td>\r
100     <td>%s</td>\r
101     <td>%s</td>\r
102   </tr>"""  % (FvName, FvGuid, FvSize)\r
103             self.WriteLn(Content)\r
104 \r
105         Content = """    <td colspan="3"><table width="100%%"  border="1">\r
106       <tr>"""\r
107         self.WriteLn(Content)\r
108 \r
109         EotGlobalData.gOP_DISPATCH_ORDER.write('Dispatched:\n')\r
110         for FfsId in FvObj.OrderedFfsDict:\r
111             self.GenerateFfs(FvObj.OrderedFfsDict[FfsId])\r
112         Content = """     </table></td>\r
113   </tr>"""\r
114         self.WriteLn(Content)\r
115 \r
116         # For UnDispatched\r
117         Content = """    <td colspan="3"><table width="100%%"  border="1">\r
118       <tr>\r
119         <tr><strong>UnDispatched</strong></tr>"""\r
120         self.WriteLn(Content)\r
121 \r
122         EotGlobalData.gOP_DISPATCH_ORDER.write('\nUnDispatched:\n')\r
123         for FfsId in FvObj.UnDispatchedFfsDict:\r
124             self.GenerateFfs(FvObj.UnDispatchedFfsDict[FfsId])\r
125         Content = """     </table></td>\r
126   </tr>"""\r
127         self.WriteLn(Content)\r
128 \r
129     ## GenerateDepex() method\r
130     #\r
131     #  Generate Depex information\r
132     #\r
133     #  @param  self: The object pointer\r
134     #  @param DepexString: A DEPEX string needed to be parsed\r
135     #\r
136     def GenerateDepex(self, DepexString):\r
137         NonGuidList = ['AND', 'OR', 'NOT', 'BEFORE', 'AFTER', 'TRUE', 'FALSE']\r
138         ItemList = DepexString.split(' ')\r
139         DepexString = ''\r
140         for Item in ItemList:\r
141             if Item not in NonGuidList:\r
142                 SqlCommand = """select DISTINCT GuidName from Report where GuidValue like '%s' and ItemMode = 'Produced' group by GuidName""" % (Item)\r
143                 RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
144                 if RecordSet != []:\r
145                     Item = RecordSet[0][0]\r
146             DepexString = DepexString + Item + ' '\r
147         Content = """                <tr>\r
148                   <td width="5%%"></td>\r
149                   <td width="95%%">%s</td>\r
150                 </tr>""" % (DepexString)\r
151         self.WriteLn(Content)\r
152 \r
153     ## GeneratePpi() method\r
154     #\r
155     #  Generate PPI information\r
156     #\r
157     #  @param self: The object pointer\r
158     #  @param Name: CName of a GUID\r
159     #  @param Guid: Value of a GUID\r
160     #  @param Type: Type of a GUID\r
161     #\r
162     def GeneratePpi(self, Name, Guid, Type):\r
163         self.GeneratePpiProtocol('Ppi', Name, Guid, Type, self.PpiIndex)\r
164 \r
165     ## GenerateProtocol() method\r
166     #\r
167     #  Generate PROTOCOL information\r
168     #\r
169     #  @param self: The object pointer\r
170     #  @param Name: CName of a GUID\r
171     #  @param Guid: Value of a GUID\r
172     #  @param Type: Type of a GUID\r
173     #\r
174     def GenerateProtocol(self, Name, Guid, Type):\r
175         self.GeneratePpiProtocol('Protocol', Name, Guid, Type, self.ProtocolIndex)\r
176 \r
177     ## GeneratePpiProtocol() method\r
178     #\r
179     #  Generate PPI/PROTOCOL information\r
180     #\r
181     #  @param self: The object pointer\r
182     #  @param Model: Model of a GUID, PPI or PROTOCOL\r
183     #  @param Name: Name of a GUID\r
184     #  @param Guid: Value of a GUID\r
185     #  @param Type: Type of a GUID\r
186     #  @param CName: CName(Index) of a GUID\r
187     #\r
188     def GeneratePpiProtocol(self, Model, Name, Guid, Type, CName):\r
189         Content = """                <tr>\r
190                   <td width="5%%"></td>\r
191                   <td width="10%%">%s</td>\r
192                   <td width="85%%" colspan="3">%s</td>\r
193                   <!-- %s -->\r
194                 </tr>""" % (Model, Name, Guid)\r
195         self.WriteLn(Content)\r
196         if Type == 'Produced':\r
197             SqlCommand = """select DISTINCT SourceFileFullPath, BelongsToFunction from Report where GuidName like '%s' and ItemMode = 'Callback'""" % Name\r
198             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
199             for Record in RecordSet:\r
200                 SqlCommand = """select FullPath from File\r
201                                 where ID = (\r
202                                 select DISTINCT BelongsToFile from Inf\r
203                                 where Value1 like '%s')""" % Record[0]\r
204                 ModuleSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
205                 Inf = ModuleSet[0][0].replace(EotGlobalData.gMACRO['WORKSPACE'], '.')\r
206                 Function = Record[1]\r
207                 Address = ''\r
208                 for Item in EotGlobalData.gMap:\r
209                     if Function in EotGlobalData.gMap[Item]:\r
210                         Address = EotGlobalData.gMap[Item][Function]\r
211                         break\r
212                     if '_' + Function in EotGlobalData.gMap[Item]:\r
213                         Address = EotGlobalData.gMap[Item]['_' + Function]\r
214                         break\r
215                 Content = """                <tr>\r
216                       <td width="5%%"></td>\r
217                       <td width="10%%">%s</td>\r
218                       <td width="40%%">%s</td>\r
219                       <td width="35%%">%s</td>\r
220                       <td width="10%%">%s</td>\r
221                     </tr>""" % ('Callback', Inf, Function, Address)\r
222                 self.WriteLn(Content)\r
223 \r
224     ## GenerateFfs() method\r
225     #\r
226     #  Generate FFS information\r
227     #\r
228     #  @param self: The object pointer\r
229     #  @param FfsObj: FFS object after FV image is parsed\r
230     #\r
231     def GenerateFfs(self, FfsObj):\r
232         self.FfsIndex = self.FfsIndex + 1\r
233         if FfsObj != None and FfsObj.Type in [0x03, 0x04, 0x05, 0x06, 0x07, 0x08]:\r
234             FfsGuid = FfsObj.Guid\r
235             FfsOffset = FfsObj._OFF_\r
236             FfsName = 'Unknonw Ffs Name'\r
237             FfsPath = FfsGuid\r
238             FfsType = FfsObj._TypeName[FfsObj.Type]\r
239 \r
240             # Hard code for Binary INF\r
241             if FfsGuid.upper() == '7BB28B99-61BB-11D5-9A5D-0090273FC14D':\r
242                 FfsName = 'Logo'\r
243 \r
244             if FfsGuid.upper() == '7E374E25-8E01-4FEE-87F2-390C23C606CD':\r
245                 FfsName = 'AcpiTables'\r
246 \r
247             if FfsGuid.upper() == '961578FE-B6B7-44C3-AF35-6BC705CD2B1F':\r
248                 FfsName = 'Fat'\r
249 \r
250             # Find FFS Path and Name\r
251             SqlCommand = """select Value2 from Inf\r
252                             where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)\r
253                             and Model = %s and Value1='BASE_NAME'""" % (FfsGuid, 5001, 5001)\r
254             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
255             if RecordSet != []:\r
256                 FfsName = RecordSet[0][0]\r
257 \r
258             SqlCommand = """select FullPath from File\r
259                             where ID = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)\r
260                             and Model = %s""" % (FfsGuid, 5001, 1011)\r
261             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
262             if RecordSet != []:\r
263                 FfsPath = RecordSet[0][0].replace(EotGlobalData.gMACRO['WORKSPACE'], '.')\r
264 \r
265             Content = """  <tr>\r
266       <tr class='styleFfs' id='FfsHeader%s'>\r
267         <td width="55%%"><span onclick="Display('FfsHeader%s', 'Ffs%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">%s</span></td>\r
268         <td width="15%%">%s</td>\r
269         <!--<td width="20%%">%s</td>-->\r
270         <!--<td width="20%%">%s</td>-->\r
271         <td width="10%%">%s</td>\r
272       </tr>\r
273       <tr id='Ffs%s' style='display:none;'>\r
274         <td colspan="4"><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, FfsPath, FfsName, FfsGuid, FfsOffset, FfsType, self.FfsIndex)\r
275 \r
276             self.WriteLn(Content)\r
277 \r
278             EotGlobalData.gOP_DISPATCH_ORDER.write('%s\n' %FfsName)\r
279 \r
280             if FfsObj.Depex != '':\r
281                 Content = """          <tr>\r
282             <td><span id='DepexHeader%s' class="styleDepex" onclick="Display('DepexHeader%s', 'Depex%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">&nbsp&nbspDEPEX expression</span></td>\r
283           </tr>\r
284           <tr id='Depex%s' style='display:none;'>\r
285             <td><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, self.FfsIndex)\r
286                 self.WriteLn(Content)\r
287                 self.GenerateDepex(FfsObj.Depex)\r
288                 Content = """            </table></td>\r
289           </tr>"""\r
290                 self.WriteLn(Content)\r
291             # End of DEPEX\r
292 \r
293             # Find Consumed Ppi/Protocol\r
294             SqlCommand = """select ModuleName, ItemType, GuidName, GuidValue, GuidMacro from Report\r
295                             where SourceFileFullPath in\r
296                             (select Value1 from Inf where BelongsToFile =\r
297                             (select BelongsToFile from Inf\r
298                             where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)\r
299                             and Model = %s)\r
300                             and ItemMode = 'Consumed' group by GuidName order by ItemType""" \\r
301                             % (FfsGuid, 5001, 3007)\r
302 \r
303             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
304             if RecordSet != []:\r
305                 Count = len(RecordSet)\r
306                 Content = """          <tr>\r
307             <td><span id='ConsumedHeader%s' class="styleConsumed" onclick="Display('ConsumedHeader%s', 'Consumed%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">&nbsp&nbspConsumed Ppis/Protocols List (%s)</span></td>\r
308           </tr>\r
309           <tr id='Consumed%s' style='display:none;'>\r
310             <td><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, Count, self.FfsIndex)\r
311                 self.WriteLn(Content)\r
312                 self.ProtocolIndex = 0\r
313                 for Record in RecordSet:\r
314                     self.ProtocolIndex = self.ProtocolIndex + 1\r
315                     Name = Record[2]\r
316                     CName = Record[4]\r
317                     Guid = Record[3]\r
318                     Type = Record[1]\r
319                     self.GeneratePpiProtocol(Type, Name, Guid, 'Consumed', CName)\r
320 \r
321                 Content = """            </table></td>\r
322           </tr>"""\r
323                 self.WriteLn(Content)\r
324             #End of Consumed Ppi/Portocol\r
325 \r
326             # Find Produced Ppi/Protocol\r
327             SqlCommand = """select ModuleName, ItemType, GuidName, GuidValue, GuidMacro from Report\r
328                             where SourceFileFullPath in\r
329                             (select Value1 from Inf where BelongsToFile =\r
330                             (select BelongsToFile from Inf\r
331                             where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)\r
332                             and Model = %s)\r
333                             and ItemMode = 'Produced' group by GuidName order by ItemType""" \\r
334                             % (FfsGuid, 5001, 3007)\r
335 \r
336             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)\r
337             if RecordSet != []:\r
338                 Count = len(RecordSet)\r
339                 Content = """          <tr>\r
340             <td><span id='ProducedHeader%s' class="styleProduced" onclick="Display('ProducedHeader%s', 'Produced%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">&nbsp&nbspProduced Ppis/Protocols List (%s)</span></td>\r
341           </tr>\r
342           <tr id='Produced%s' style='display:none;'>\r
343             <td><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, Count, self.FfsIndex)\r
344                 self.WriteLn(Content)\r
345                 self.PpiIndex = 0\r
346                 for Record in RecordSet:\r
347                     self.PpiIndex = self.PpiIndex + 1\r
348                     Name = Record[2]\r
349                     CName = Record[4]\r
350                     Guid = Record[3]\r
351                     Type = Record[1]\r
352                     self.GeneratePpiProtocol(Type, Name, Guid, 'Produced', CName)\r
353 \r
354                 Content = """            </table></td>\r
355           </tr>"""\r
356                 self.WriteLn(Content)\r
357             RecordSet = None\r
358             # End of Produced Ppi/Protocol\r
359 \r
360             Content = """        </table></td>\r
361         </tr>"""\r
362             self.WriteLn(Content)\r
363 \r
364     ## GenerateTail() method\r
365     #\r
366     #  Generate end tags of HTML report\r
367     #\r
368     #  @param self: The object pointer\r
369     #\r
370     def GenerateTail(self):\r
371         Tail = """</table>\r
372 </body>\r
373 </html>"""\r
374         self.WriteLn(Tail)\r
375 \r
376     ## GenerateHeader() method\r
377     #\r
378     #  Generate start tags of HTML report\r
379     #\r
380     #  @param self: The object pointer\r
381     #\r
382     def GenerateHeader(self):\r
383         Header = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\r
384 "http://www.w3.org/TR/html4/loose.dtd">\r
385 <html>\r
386 <head>\r
387 <title>Execution Order Tool Report</title>\r
388 <meta http-equiv="Content-Type" content="text/html">\r
389 <style type="text/css">\r
390 <!--\r
391 .styleFfs {\r
392     color: #006600;\r
393     font-weight: bold;\r
394 }\r
395 .styleDepex {\r
396     color: #FF0066;\r
397     font-weight: bold;\r
398 }\r
399 .styleProduced {\r
400     color: #0000FF;\r
401     font-weight: bold;\r
402 }\r
403 .styleConsumed {\r
404     color: #FF00FF;\r
405     font-weight: bold;\r
406 }\r
407 -->\r
408 </style>\r
409 <Script type="text/javascript">\r
410 function Display(ParentID, SubID)\r
411 {\r
412     SubItem = document.getElementById(SubID);\r
413     ParentItem = document.getElementById(ParentID);\r
414     if (SubItem.style.display == 'none')\r
415     {\r
416         SubItem.style.display = ''\r
417         ParentItem.style.fontWeight = 'normal'\r
418     }\r
419     else\r
420     {\r
421         SubItem.style.display = 'none'\r
422         ParentItem.style.fontWeight = 'bold'\r
423     }\r
424 \r
425 }\r
426 \r
427 function funOnMouseOver()\r
428 {\r
429     document.body.style.cursor = "hand";\r
430 }\r
431 \r
432 function funOnMouseOut()\r
433 {\r
434     document.body.style.cursor = "";\r
435 }\r
436 \r
437 </Script>\r
438 </head>\r
439 \r
440 <body>\r
441 <table width="100%%"  border="1">"""\r
442         self.WriteLn(Header)\r
443 \r
444 ##\r
445 #\r
446 # This acts like the main() function for the script, unless it is 'import'ed into another\r
447 # script.\r
448 #\r
449 if __name__ == '__main__':\r
450     # Initialize log system\r
451     FilePath = 'FVRECOVERYFLOPPY.fv'\r
452     if FilePath.lower().endswith(".fv"):\r
453         fd = open(FilePath, 'rb')\r
454         buf = array('B')\r
455         try:\r
456             buf.fromfile(fd, os.path.getsize(FilePath))\r
457         except EOFError:\r
458             pass\r
459 \r
460         fv = FirmwareVolume("FVRECOVERY", buf, 0)\r
461 \r
462     report = Report('Report.html', fv)\r
463     report.GenerateReport()\r