Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hess Chen <hesheng.chen@intel.com> Reviewed-by: Yingke Liu <yingke.d.liu@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15809 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			474 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			474 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # This file is used to create report for Eot tool
 | |
| #
 | |
| # Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| # This program and the accompanying materials
 | |
| # are licensed and made available under the terms and conditions of the BSD License
 | |
| # which accompanies this distribution.  The full text of the license may be found at
 | |
| # http://opensource.org/licenses/bsd-license.php
 | |
| #
 | |
| # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| #
 | |
| 
 | |
| ##
 | |
| # Import Modules
 | |
| #
 | |
| import Common.LongFilePathOs as os
 | |
| import EotGlobalData
 | |
| from Common.LongFilePathSupport import OpenLongFilePath as open
 | |
| 
 | |
| ## Report() class
 | |
| #
 | |
| #  This class defined Report
 | |
| #
 | |
| #  @param object: Inherited from object class
 | |
| #
 | |
| class Report(object):
 | |
|     ## The constructor
 | |
|     #
 | |
|     #  @param  self: The object pointer
 | |
|     #  @param  ReportName: name of the report
 | |
|     #  @param  FvObj: FV object after parsing FV images
 | |
|     #
 | |
|     def __init__(self, ReportName = 'Report.html', FvObj = None, DispatchName=None):
 | |
|         self.ReportName = ReportName
 | |
|         self.Op = open(ReportName, 'w+')
 | |
|         self.DispatchList = None
 | |
|         if DispatchName:
 | |
|             self.DispatchList = open(DispatchName, 'w+')
 | |
|         self.FvObj = FvObj
 | |
|         self.FfsIndex = 0
 | |
|         self.PpiIndex = 0
 | |
|         self.ProtocolIndex = 0
 | |
|         if EotGlobalData.gMACRO['EFI_SOURCE'] == '':
 | |
|             EotGlobalData.gMACRO['EFI_SOURCE'] = EotGlobalData.gMACRO['EDK_SOURCE']
 | |
| 
 | |
|     ## WriteLn() method
 | |
|     #
 | |
|     #  Write a line in the report
 | |
|     #
 | |
|     #  @param  self: The object pointer
 | |
|     #  @param Line:  The lint to be written into
 | |
|     #
 | |
|     def WriteLn(self, Line):
 | |
|         self.Op.write('%s\n' % Line)
 | |
| 
 | |
|     ## GenerateReport() method
 | |
|     #
 | |
|     #  A caller to generate report
 | |
|     #
 | |
|     #  @param  self: The object pointer
 | |
|     #
 | |
|     def GenerateReport(self):
 | |
|         self.GenerateHeader()
 | |
|         self.GenerateFv()
 | |
|         self.GenerateTail()
 | |
|         self.Op.close()
 | |
|         self.GenerateUnDispatchedList()
 | |
| 
 | |
|     ## GenerateUnDispatchedList() method
 | |
|     #
 | |
|     #  Create a list for not dispatched items
 | |
|     #
 | |
|     #  @param  self: The object pointer
 | |
|     #
 | |
|     def GenerateUnDispatchedList(self):
 | |
|         FvObj = self.FvObj
 | |
|         EotGlobalData.gOP_UN_DISPATCHED.write('%s\n' % FvObj.Name)
 | |
|         for Item in FvObj.UnDispatchedFfsDict:
 | |
|             EotGlobalData.gOP_UN_DISPATCHED.write('%s\n' % FvObj.UnDispatchedFfsDict[Item])
 | |
| 
 | |
|     ## GenerateFv() method
 | |
|     #
 | |
|     #  Generate FV information
 | |
|     #
 | |
|     #  @param  self: The object pointer
 | |
|     #
 | |
|     def GenerateFv(self):
 | |
|         FvObj = self.FvObj
 | |
|         Content = """  <tr>
 | |
|     <td width="20%%"><strong>Name</strong></td>
 | |
|     <td width="60%%"><strong>Guid</strong></td>
 | |
|     <td width="20%%"><strong>Size</strong></td>
 | |
|   </tr>"""
 | |
|         self.WriteLn(Content)
 | |
| 
 | |
|         for Info in FvObj.BasicInfo:
 | |
|             FvName = Info[0]
 | |
|             FvGuid = Info[1]
 | |
|             FvSize = Info[2]
 | |
| 
 | |
|             Content = """  <tr>
 | |
|     <td>%s</td>
 | |
|     <td>%s</td>
 | |
|     <td>%s</td>
 | |
|   </tr>"""  % (FvName, FvGuid, FvSize)
 | |
|             self.WriteLn(Content)
 | |
| 
 | |
|         Content = """    <td colspan="3"><table width="100%%"  border="1">
 | |
|       <tr>"""
 | |
|         self.WriteLn(Content)
 | |
| 
 | |
|         EotGlobalData.gOP_DISPATCH_ORDER.write('Dispatched:\n')
 | |
|         for FfsId in FvObj.OrderedFfsDict:
 | |
|             self.GenerateFfs(FvObj.OrderedFfsDict[FfsId])
 | |
|         Content = """     </table></td>
 | |
|   </tr>"""
 | |
|         self.WriteLn(Content)
 | |
| 
 | |
|         # For UnDispatched
 | |
|         Content = """    <td colspan="3"><table width="100%%"  border="1">
 | |
|       <tr>
 | |
|         <tr><strong>UnDispatched</strong></tr>"""
 | |
|         self.WriteLn(Content)
 | |
| 
 | |
|         EotGlobalData.gOP_DISPATCH_ORDER.write('\nUnDispatched:\n')
 | |
|         for FfsId in FvObj.UnDispatchedFfsDict:
 | |
|             self.GenerateFfs(FvObj.UnDispatchedFfsDict[FfsId])
 | |
|         Content = """     </table></td>
 | |
|   </tr>"""
 | |
|         self.WriteLn(Content)
 | |
| 
 | |
|     ## GenerateDepex() method
 | |
|     #
 | |
|     #  Generate Depex information
 | |
|     #
 | |
|     #  @param  self: The object pointer
 | |
|     #  @param DepexString: A DEPEX string needed to be parsed
 | |
|     #
 | |
|     def GenerateDepex(self, DepexString):
 | |
|         NonGuidList = ['AND', 'OR', 'NOT', 'BEFORE', 'AFTER', 'TRUE', 'FALSE']
 | |
|         ItemList = DepexString.split(' ')
 | |
|         DepexString = ''
 | |
|         for Item in ItemList:
 | |
|             if Item not in NonGuidList:
 | |
|                 SqlCommand = """select DISTINCT GuidName from Report where GuidValue like '%s' and ItemMode = 'Produced' group by GuidName""" % (Item)
 | |
|                 RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|                 if RecordSet != []:
 | |
|                     Item = RecordSet[0][0]
 | |
|             DepexString = DepexString + Item + ' '
 | |
|         Content = """                <tr>
 | |
|                   <td width="5%%"></td>
 | |
|                   <td width="95%%">%s</td>
 | |
|                 </tr>""" % (DepexString)
 | |
|         self.WriteLn(Content)
 | |
| 
 | |
|     ## GeneratePpi() method
 | |
|     #
 | |
|     #  Generate PPI information
 | |
|     #
 | |
|     #  @param self: The object pointer
 | |
|     #  @param Name: CName of a GUID
 | |
|     #  @param Guid: Value of a GUID
 | |
|     #  @param Type: Type of a GUID
 | |
|     #
 | |
|     def GeneratePpi(self, Name, Guid, Type):
 | |
|         self.GeneratePpiProtocol('Ppi', Name, Guid, Type, self.PpiIndex)
 | |
| 
 | |
|     ## GenerateProtocol() method
 | |
|     #
 | |
|     #  Generate PROTOCOL information
 | |
|     #
 | |
|     #  @param self: The object pointer
 | |
|     #  @param Name: CName of a GUID
 | |
|     #  @param Guid: Value of a GUID
 | |
|     #  @param Type: Type of a GUID
 | |
|     #
 | |
|     def GenerateProtocol(self, Name, Guid, Type):
 | |
|         self.GeneratePpiProtocol('Protocol', Name, Guid, Type, self.ProtocolIndex)
 | |
| 
 | |
|     ## GeneratePpiProtocol() method
 | |
|     #
 | |
|     #  Generate PPI/PROTOCOL information
 | |
|     #
 | |
|     #  @param self: The object pointer
 | |
|     #  @param Model: Model of a GUID, PPI or PROTOCOL
 | |
|     #  @param Name: Name of a GUID
 | |
|     #  @param Guid: Value of a GUID
 | |
|     #  @param Type: Type of a GUID
 | |
|     #  @param CName: CName(Index) of a GUID
 | |
|     #
 | |
|     def GeneratePpiProtocol(self, Model, Name, Guid, Type, CName):
 | |
|         Content = """                <tr>
 | |
|                   <td width="5%%"></td>
 | |
|                   <td width="10%%">%s</td>
 | |
|                   <td width="85%%" colspan="3">%s</td>
 | |
|                   <!-- %s -->
 | |
|                 </tr>""" % (Model, Name, Guid)
 | |
|         self.WriteLn(Content)
 | |
|         if Type == 'Produced':
 | |
|             SqlCommand = """select DISTINCT SourceFileFullPath, BelongsToFunction from Report where GuidName like '%s' and ItemMode = 'Callback'""" % Name
 | |
|             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|             for Record in RecordSet:
 | |
|                 SqlCommand = """select FullPath from File
 | |
|                                 where ID = (
 | |
|                                 select DISTINCT BelongsToFile from Inf
 | |
|                                 where Value1 like '%s')""" % Record[0]
 | |
|                 ModuleSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|                 Inf = ModuleSet[0][0].replace(EotGlobalData.gMACRO['WORKSPACE'], '.')
 | |
|                 Function = Record[1]
 | |
|                 Address = ''
 | |
|                 for Item in EotGlobalData.gMap:
 | |
|                     if Function in EotGlobalData.gMap[Item]:
 | |
|                         Address = EotGlobalData.gMap[Item][Function]
 | |
|                         break
 | |
|                     if '_' + Function in EotGlobalData.gMap[Item]:
 | |
|                         Address = EotGlobalData.gMap[Item]['_' + Function]
 | |
|                         break
 | |
|                 Content = """                <tr>
 | |
|                       <td width="5%%"></td>
 | |
|                       <td width="10%%">%s</td>
 | |
|                       <td width="40%%">%s</td>
 | |
|                       <td width="35%%">%s</td>
 | |
|                       <td width="10%%">%s</td>
 | |
|                     </tr>""" % ('Callback', Inf, Function, Address)
 | |
|                 self.WriteLn(Content)
 | |
| 
 | |
|     ## GenerateFfs() method
 | |
|     #
 | |
|     #  Generate FFS information
 | |
|     #
 | |
|     #  @param self: The object pointer
 | |
|     #  @param FfsObj: FFS object after FV image is parsed
 | |
|     #
 | |
|     def GenerateFfs(self, FfsObj):
 | |
|         self.FfsIndex = self.FfsIndex + 1
 | |
|         if FfsObj != None and FfsObj.Type in [0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xA]:
 | |
|             FfsGuid = FfsObj.Guid
 | |
|             FfsOffset = FfsObj._OFF_
 | |
|             FfsName = 'Unknown-Module'
 | |
|             FfsPath = FfsGuid
 | |
|             FfsType = FfsObj._TypeName[FfsObj.Type]
 | |
| 
 | |
|             # Hard code for Binary INF
 | |
|             if FfsGuid.upper() == '7BB28B99-61BB-11D5-9A5D-0090273FC14D':
 | |
|                 FfsName = 'Logo'
 | |
| 
 | |
|             if FfsGuid.upper() == '7E374E25-8E01-4FEE-87F2-390C23C606CD':
 | |
|                 FfsName = 'AcpiTables'
 | |
| 
 | |
|             if FfsGuid.upper() == '961578FE-B6B7-44C3-AF35-6BC705CD2B1F':
 | |
|                 FfsName = 'Fat'
 | |
| 
 | |
|             # Find FFS Path and Name
 | |
|             SqlCommand = """select Value2 from Inf
 | |
|                             where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
 | |
|                             and Model = %s and Value1='BASE_NAME'""" % (FfsGuid, 5001, 5001)
 | |
|             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|             if RecordSet != []:
 | |
|                 FfsName = RecordSet[0][0]
 | |
| 
 | |
|             SqlCommand = """select FullPath from File
 | |
|                             where ID = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
 | |
|                             and Model = %s""" % (FfsGuid, 5001, 1011)
 | |
|             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|             if RecordSet != []:
 | |
|                 FfsPath = RecordSet[0][0]
 | |
| 
 | |
|             Content = """  <tr>
 | |
|       <tr class='styleFfs' id='FfsHeader%s'>
 | |
|         <td width="55%%"><span onclick="Display('FfsHeader%s', 'Ffs%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">%s</span></td>
 | |
|         <td width="15%%">%s</td>
 | |
|         <!--<td width="20%%">%s</td>-->
 | |
|         <!--<td width="20%%">%s</td>-->
 | |
|         <td width="10%%">%s</td>
 | |
|       </tr>
 | |
|       <tr id='Ffs%s' style='display:none;'>
 | |
|         <td colspan="4"><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, FfsPath, FfsName, FfsGuid, FfsOffset, FfsType, self.FfsIndex)
 | |
|             
 | |
|             if self.DispatchList:
 | |
|                 if FfsObj.Type in [0x04, 0x06]:
 | |
|                     self.DispatchList.write("%s %s %s %s\n" % (FfsGuid, "P", FfsName, FfsPath))
 | |
|                 if FfsObj.Type in [0x05, 0x07, 0x08, 0x0A]:
 | |
|                     self.DispatchList.write("%s %s %s %s\n" % (FfsGuid, "D", FfsName, FfsPath))
 | |
|                
 | |
|             self.WriteLn(Content)
 | |
| 
 | |
|             EotGlobalData.gOP_DISPATCH_ORDER.write('%s\n' %FfsName)
 | |
| 
 | |
|             if FfsObj.Depex != '':
 | |
|                 Content = """          <tr>
 | |
|             <td><span id='DepexHeader%s' class="styleDepex" onclick="Display('DepexHeader%s', 'Depex%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">  DEPEX expression</span></td>
 | |
|           </tr>
 | |
|           <tr id='Depex%s' style='display:none;'>
 | |
|             <td><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, self.FfsIndex)
 | |
|                 self.WriteLn(Content)
 | |
|                 self.GenerateDepex(FfsObj.Depex)
 | |
|                 Content = """            </table></td>
 | |
|           </tr>"""
 | |
|                 self.WriteLn(Content)
 | |
|             # End of DEPEX
 | |
| 
 | |
|             # Find Consumed Ppi/Protocol
 | |
|             SqlCommand = """select ModuleName, ItemType, GuidName, GuidValue, GuidMacro from Report
 | |
|                             where SourceFileFullPath in
 | |
|                             (select Value1 from Inf where BelongsToFile =
 | |
|                             (select BelongsToFile from Inf
 | |
|                             where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
 | |
|                             and Model = %s)
 | |
|                             and ItemMode = 'Consumed' group by GuidName order by ItemType""" \
 | |
|                             % (FfsGuid, 5001, 3007)
 | |
| 
 | |
|             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|             if RecordSet != []:
 | |
|                 Count = len(RecordSet)
 | |
|                 Content = """          <tr>
 | |
|             <td><span id='ConsumedHeader%s' class="styleConsumed" onclick="Display('ConsumedHeader%s', 'Consumed%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">  Consumed Ppis/Protocols List (%s)</span></td>
 | |
|           </tr>
 | |
|           <tr id='Consumed%s' style='display:none;'>
 | |
|             <td><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, Count, self.FfsIndex)
 | |
|                 self.WriteLn(Content)
 | |
|                 self.ProtocolIndex = 0
 | |
|                 for Record in RecordSet:
 | |
|                     self.ProtocolIndex = self.ProtocolIndex + 1
 | |
|                     Name = Record[2]
 | |
|                     CName = Record[4]
 | |
|                     Guid = Record[3]
 | |
|                     Type = Record[1]
 | |
|                     self.GeneratePpiProtocol(Type, Name, Guid, 'Consumed', CName)
 | |
| 
 | |
|                 Content = """            </table></td>
 | |
|           </tr>"""
 | |
|                 self.WriteLn(Content)
 | |
|             #End of Consumed Ppi/Portocol
 | |
| 
 | |
|             # Find Produced Ppi/Protocol
 | |
|             SqlCommand = """select ModuleName, ItemType, GuidName, GuidValue, GuidMacro from Report
 | |
|                             where SourceFileFullPath in
 | |
|                             (select Value1 from Inf where BelongsToFile =
 | |
|                             (select BelongsToFile from Inf
 | |
|                             where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
 | |
|                             and Model = %s)
 | |
|                             and ItemMode = 'Produced' group by GuidName order by ItemType""" \
 | |
|                             % (FfsGuid, 5001, 3007)
 | |
| 
 | |
|             RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
 | |
|             if RecordSet != []:
 | |
|                 Count = len(RecordSet)
 | |
|                 Content = """          <tr>
 | |
|             <td><span id='ProducedHeader%s' class="styleProduced" onclick="Display('ProducedHeader%s', 'Produced%s')" onMouseOver="funOnMouseOver()" onMouseOut="funOnMouseOut()">  Produced Ppis/Protocols List (%s)</span></td>
 | |
|           </tr>
 | |
|           <tr id='Produced%s' style='display:none;'>
 | |
|             <td><table width="100%%"  border="1">""" % (self.FfsIndex, self.FfsIndex, self.FfsIndex, Count, self.FfsIndex)
 | |
|                 self.WriteLn(Content)
 | |
|                 self.PpiIndex = 0
 | |
|                 for Record in RecordSet:
 | |
|                     self.PpiIndex = self.PpiIndex + 1
 | |
|                     Name = Record[2]
 | |
|                     CName = Record[4]
 | |
|                     Guid = Record[3]
 | |
|                     Type = Record[1]
 | |
|                     self.GeneratePpiProtocol(Type, Name, Guid, 'Produced', CName)
 | |
| 
 | |
|                 Content = """            </table></td>
 | |
|           </tr>"""
 | |
|                 self.WriteLn(Content)
 | |
|             RecordSet = None
 | |
|             # End of Produced Ppi/Protocol
 | |
| 
 | |
|             Content = """        </table></td>
 | |
|         </tr>"""
 | |
|             self.WriteLn(Content)
 | |
| 
 | |
|     ## GenerateTail() method
 | |
|     #
 | |
|     #  Generate end tags of HTML report
 | |
|     #
 | |
|     #  @param self: The object pointer
 | |
|     #
 | |
|     def GenerateTail(self):
 | |
|         Tail = """</table>
 | |
| </body>
 | |
| </html>"""
 | |
|         self.WriteLn(Tail)
 | |
| 
 | |
|     ## GenerateHeader() method
 | |
|     #
 | |
|     #  Generate start tags of HTML report
 | |
|     #
 | |
|     #  @param self: The object pointer
 | |
|     #
 | |
|     def GenerateHeader(self):
 | |
|         Header = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 | |
| "http://www.w3.org/TR/html4/loose.dtd">
 | |
| <html>
 | |
| <head>
 | |
| <title>Execution Order Tool Report</title>
 | |
| <meta http-equiv="Content-Type" content="text/html">
 | |
| <style type="text/css">
 | |
| <!--
 | |
| .styleFfs {
 | |
|     color: #006600;
 | |
|     font-weight: bold;
 | |
| }
 | |
| .styleDepex {
 | |
|     color: #FF0066;
 | |
|     font-weight: bold;
 | |
| }
 | |
| .styleProduced {
 | |
|     color: #0000FF;
 | |
|     font-weight: bold;
 | |
| }
 | |
| .styleConsumed {
 | |
|     color: #FF00FF;
 | |
|     font-weight: bold;
 | |
| }
 | |
| -->
 | |
| </style>
 | |
| <Script type="text/javascript">
 | |
| function Display(ParentID, SubID)
 | |
| {
 | |
|     SubItem = document.getElementById(SubID);
 | |
|     ParentItem = document.getElementById(ParentID);
 | |
|     if (SubItem.style.display == 'none')
 | |
|     {
 | |
|         SubItem.style.display = ''
 | |
|         ParentItem.style.fontWeight = 'normal'
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         SubItem.style.display = 'none'
 | |
|         ParentItem.style.fontWeight = 'bold'
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| function funOnMouseOver()
 | |
| {
 | |
|     document.body.style.cursor = "hand";
 | |
| }
 | |
| 
 | |
| function funOnMouseOut()
 | |
| {
 | |
|     document.body.style.cursor = "";
 | |
| }
 | |
| 
 | |
| </Script>
 | |
| </head>
 | |
| 
 | |
| <body>
 | |
| <table width="100%%"  border="1">"""
 | |
|         self.WriteLn(Header)
 | |
| 
 | |
| ##
 | |
| #
 | |
| # This acts like the main() function for the script, unless it is 'import'ed into another
 | |
| # script.
 | |
| #
 | |
| if __name__ == '__main__':
 | |
|     # Initialize log system
 | |
|     FilePath = 'FVRECOVERYFLOPPY.fv'
 | |
|     if FilePath.lower().endswith(".fv"):
 | |
|         fd = open(FilePath, 'rb')
 | |
|         buf = array('B')
 | |
|         try:
 | |
|             buf.fromfile(fd, os.path.getsize(FilePath))
 | |
|         except EOFError:
 | |
|             pass
 | |
| 
 | |
|         fv = FirmwareVolume("FVRECOVERY", buf, 0)
 | |
| 
 | |
|     report = Report('Report.html', fv)
 | |
|     report.GenerateReport()
 |