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