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