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