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