1## @file 2# Parse FV image 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## Import Modules 15# 16import Common.LongFilePathOs as os 17import re 18import sys 19import uuid 20import struct 21import codecs 22import copy 23 24from UserDict import IterableUserDict 25from cStringIO import StringIO 26from array import array 27from Common.LongFilePathSupport import OpenLongFilePath as open 28from CommonDataClass import * 29from Common.Misc import sdict, GuidStructureStringToGuidString 30 31import Common.EdkLogger as EdkLogger 32 33import EotGlobalData 34 35# Global definiton 36gFfsPrintTitle = "%-36s %-21s %8s %8s %8s %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME") 37gFfsPrintFormat = "%36s %-21s %8X %8X %8X %4s %-36s" 38gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X" 39gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6' 40gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881' 41gIndention = -4 42 43## Image() class 44# 45# A class for Image 46# 47class Image(array): 48 _HEADER_ = struct.Struct("") 49 _HEADER_SIZE_ = _HEADER_.size 50 51 def __new__(cls, *args, **kwargs): 52 return array.__new__(cls, 'B') 53 54 def __init__(m, ID=None): 55 if ID == None: 56 m._ID_ = str(uuid.uuid1()).upper() 57 else: 58 m._ID_ = ID 59 m._BUF_ = None 60 m._LEN_ = None 61 m._OFF_ = None 62 63 m._SubImages = sdict() # {offset: Image()} 64 65 array.__init__(m, 'B') 66 67 def __repr__(m): 68 return m._ID_ 69 70 def __len__(m): 71 Len = array.__len__(m) 72 for Offset in m._SubImages: 73 Len += len(m._SubImages[Offset]) 74 return Len 75 76 def _Unpack(m): 77 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_]) 78 return len(m) 79 80 def _Pack(m, PadByte=0xFF): 81 raise NotImplementedError 82 83 def frombuffer(m, Buffer, Offset=0, Size=None): 84 m._BUF_ = Buffer 85 m._OFF_ = Offset 86 # we may need the Size information in advance if it's given 87 m._LEN_ = Size 88 m._LEN_ = m._Unpack() 89 90 def empty(m): 91 del m[0:] 92 93 def GetField(m, FieldStruct, Offset=0): 94 return FieldStruct.unpack_from(m, Offset) 95 96 def SetField(m, FieldStruct, Offset, *args): 97 # check if there's enough space 98 Size = FieldStruct.size 99 if Size > len(m): 100 m.extend([0] * (Size - len(m))) 101 FieldStruct.pack_into(m, Offset, *args) 102 103 def _SetData(m, Data): 104 if len(m) < m._HEADER_SIZE_: 105 m.extend([0] * (m._HEADER_SIZE_ - len(m))) 106 else: 107 del m[m._HEADER_SIZE_:] 108 m.extend(Data) 109 110 def _GetData(m): 111 if len(m) > m._HEADER_SIZE_: 112 return m[m._HEADER_SIZE_:] 113 return None 114 115 Data = property(_GetData, _SetData) 116 117## FirmwareVolume() class 118# 119# A class for Firmware Volume 120# 121class FirmwareVolume(Image): 122 # Read FvLength, Attributes, HeaderLength, Checksum 123 _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H") 124 _HEADER_SIZE_ = _HEADER_.size 125 126 _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3" 127 128 _GUID_ = struct.Struct("16x 1I2H8B") 129 _LENGTH_ = struct.Struct("16x 16x 1Q") 130 _SIG_ = struct.Struct("16x 16x 8x 1I") 131 _ATTR_ = struct.Struct("16x 16x 8x 4x 1I") 132 _HLEN_ = struct.Struct("16x 16x 8x 4x 4x 1H") 133 _CHECKSUM_ = struct.Struct("16x 16x 8x 4x 4x 2x 1H") 134 135 def __init__(self, Name=''): 136 Image.__init__(self) 137 self.Name = Name 138 self.FfsDict = sdict() 139 self.OrderedFfsDict = sdict() 140 self.UnDispatchedFfsDict = sdict() 141 self.NoDepexFfsDict = sdict() 142 self.ProtocolList = sdict() 143 144 def CheckArchProtocol(self): 145 for Item in EotGlobalData.gArchProtocolGuids: 146 if Item.lower() not in EotGlobalData.gProtocolList: 147 148 return False 149 150 return True 151 152 def ParseDepex(self, Depex, Type): 153 List = None 154 if Type == 'Ppi': 155 List = EotGlobalData.gPpiList 156 if Type == 'Protocol': 157 List = EotGlobalData.gProtocolList 158 DepexStack = [] 159 DepexList = [] 160 DepexString = '' 161 FileDepex = None 162 CouldBeLoaded = True 163 for Index in range(0, len(Depex.Expression)): 164 Item = Depex.Expression[Index] 165 if Item == 0x00: 166 Index = Index + 1 167 Guid = gGuidStringFormat % Depex.Expression[Index] 168 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08: 169 return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE']) 170 elif Item == 0x01: 171 Index = Index + 1 172 Guid = gGuidStringFormat % Depex.Expression[Index] 173 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08: 174 return (True, 'AFTER %s' % Guid, [Guid, 'AFTER']) 175 elif Item == 0x02: 176 Index = Index + 1 177 Guid = gGuidStringFormat % Depex.Expression[Index] 178 if Guid.lower() in List: 179 DepexStack.append(True) 180 DepexList.append(Guid) 181 else: 182 DepexStack.append(False) 183 DepexList.append(Guid) 184 continue 185 elif Item == 0x03 or Item == 0x04: 186 DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop()))) 187 DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop())) 188 elif Item == 0x05: 189 DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop()))) 190 DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop())) 191 elif Item == 0x06: 192 DepexStack.append(True) 193 DepexList.append('TRUE') 194 DepexString = DepexString + 'TRUE' + ' ' 195 elif Item == 0x07: 196 DepexStack.append(False) 197 DepexList.append('False') 198 DepexString = DepexString + 'FALSE' + ' ' 199 elif Item == 0x08: 200 if Index != len(Depex.Expression) - 1: 201 CouldBeLoaded = False 202 else: 203 CouldBeLoaded = DepexStack.pop() 204 else: 205 CouldBeLoaded = False 206 if DepexList != []: 207 DepexString = DepexList[0].strip() 208 return (CouldBeLoaded, DepexString, FileDepex) 209 210 def Dispatch(self, Db = None): 211 if Db == None: 212 return False 213 self.UnDispatchedFfsDict = copy.copy(self.FfsDict) 214 # Find PeiCore, DexCore, PeiPriori, DxePriori first 215 FfsSecCoreGuid = None 216 FfsPeiCoreGuid = None 217 FfsDxeCoreGuid = None 218 FfsPeiPrioriGuid = None 219 FfsDxePrioriGuid = None 220 for FfsID in self.UnDispatchedFfsDict: 221 Ffs = self.UnDispatchedFfsDict[FfsID] 222 if Ffs.Type == 0x03: 223 FfsSecCoreGuid = FfsID 224 continue 225 if Ffs.Type == 0x04: 226 FfsPeiCoreGuid = FfsID 227 continue 228 if Ffs.Type == 0x05: 229 FfsDxeCoreGuid = FfsID 230 continue 231 if Ffs.Guid.lower() == gPeiAprioriFileNameGuid: 232 FfsPeiPrioriGuid = FfsID 233 continue 234 if Ffs.Guid.lower() == gAprioriGuid: 235 FfsDxePrioriGuid = FfsID 236 continue 237 238 # Parse SEC_CORE first 239 if FfsSecCoreGuid != None: 240 self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid) 241 self.LoadPpi(Db, FfsSecCoreGuid) 242 243 # Parse PEI first 244 if FfsPeiCoreGuid != None: 245 self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid) 246 self.LoadPpi(Db, FfsPeiCoreGuid) 247 if FfsPeiPrioriGuid != None: 248 # Load PEIM described in priori file 249 FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid) 250 if len(FfsPeiPriori.Sections) == 1: 251 Section = FfsPeiPriori.Sections.popitem()[1] 252 if Section.Type == 0x19: 253 GuidStruct = struct.Struct('1I2H8B') 254 Start = 4 255 while len(Section) > Start: 256 Guid = GuidStruct.unpack_from(Section[Start : Start + 16]) 257 GuidString = gGuidStringFormat % Guid 258 Start = Start + 16 259 if GuidString in self.UnDispatchedFfsDict: 260 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString) 261 self.LoadPpi(Db, GuidString) 262 263 self.DisPatchPei(Db) 264 265 # Parse DXE then 266 if FfsDxeCoreGuid != None: 267 self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid) 268 self.LoadProtocol(Db, FfsDxeCoreGuid) 269 if FfsDxePrioriGuid != None: 270 # Load PEIM described in priori file 271 FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid) 272 if len(FfsDxePriori.Sections) == 1: 273 Section = FfsDxePriori.Sections.popitem()[1] 274 if Section.Type == 0x19: 275 GuidStruct = struct.Struct('1I2H8B') 276 Start = 4 277 while len(Section) > Start: 278 Guid = GuidStruct.unpack_from(Section[Start : Start + 16]) 279 GuidString = gGuidStringFormat % Guid 280 Start = Start + 16 281 if GuidString in self.UnDispatchedFfsDict: 282 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString) 283 self.LoadProtocol(Db, GuidString) 284 285 self.DisPatchDxe(Db) 286 287 def DisPatchNoDepexFfs(self, Db): 288 # Last Load Drivers without Depex 289 for FfsID in self.NoDepexFfsDict: 290 NewFfs = self.NoDepexFfsDict.pop(FfsID) 291 self.OrderedFfsDict[FfsID] = NewFfs 292 self.LoadProtocol(Db, FfsID) 293 294 return True 295 296 def LoadCallbackProtocol(self): 297 IsLoad = True 298 for Protocol in self.ProtocolList: 299 for Callback in self.ProtocolList[Protocol][1]: 300 if Callback[0] not in self.OrderedFfsDict.keys(): 301 IsLoad = False 302 continue 303 if IsLoad: 304 EotGlobalData.gProtocolList[Protocol.lower()] = self.ProtocolList[Protocol][0] 305 self.ProtocolList.pop(Protocol) 306 307 def LoadProtocol(self, Db, ModuleGuid): 308 SqlCommand = """select GuidValue from Report 309 where SourceFileFullPath in 310 (select Value1 from Inf where BelongsToFile = 311 (select BelongsToFile from Inf 312 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s) 313 and Model = %s) 314 and ItemType = 'Protocol' and ItemMode = 'Produced'""" \ 315 % (ModuleGuid, 5001, 3007) 316 RecordSet = Db.TblReport.Exec(SqlCommand) 317 for Record in RecordSet: 318 SqlCommand = """select Value2 from Inf where BelongsToFile = 319 (select DISTINCT BelongsToFile from Inf 320 where Value1 = 321 (select SourceFileFullPath from Report 322 where GuidValue like '%s' and ItemMode = 'Callback')) 323 and Value1 = 'FILE_GUID'""" % Record[0] 324 CallBackSet = Db.TblReport.Exec(SqlCommand) 325 if CallBackSet != []: 326 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid 327 else: 328 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid 329 330 def LoadPpi(self, Db, ModuleGuid): 331 SqlCommand = """select GuidValue from Report 332 where SourceFileFullPath in 333 (select Value1 from Inf where BelongsToFile = 334 (select BelongsToFile from Inf 335 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s) 336 and Model = %s) 337 and ItemType = 'Ppi' and ItemMode = 'Produced'""" \ 338 % (ModuleGuid, 5001, 3007) 339 RecordSet = Db.TblReport.Exec(SqlCommand) 340 for Record in RecordSet: 341 EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid 342 343 def DisPatchDxe(self, Db): 344 IsInstalled = False 345 ScheduleList = sdict() 346 for FfsID in self.UnDispatchedFfsDict: 347 CouldBeLoaded = False 348 DepexString = '' 349 FileDepex = None 350 Ffs = self.UnDispatchedFfsDict[FfsID] 351 if Ffs.Type == 0x07: 352 # Get Depex 353 IsFoundDepex = False 354 for Section in Ffs.Sections.values(): 355 # Find Depex 356 if Section.Type == 0x13: 357 IsFoundDepex = True 358 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol') 359 break 360 if Section.Type == 0x01: 361 CompressSections = Section._SubImages[4] 362 for CompressSection in CompressSections.Sections: 363 if CompressSection.Type == 0x13: 364 IsFoundDepex = True 365 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol') 366 break 367 if CompressSection.Type == 0x02: 368 NewSections = CompressSection._SubImages[4] 369 for NewSection in NewSections.Sections: 370 if NewSection.Type == 0x13: 371 IsFoundDepex = True 372 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol') 373 break 374 375 # Not find Depex 376 if not IsFoundDepex: 377 CouldBeLoaded = self.CheckArchProtocol() 378 DepexString = '' 379 FileDepex = None 380 381 # Append New Ffs 382 if CouldBeLoaded: 383 IsInstalled = True 384 NewFfs = self.UnDispatchedFfsDict.pop(FfsID) 385 NewFfs.Depex = DepexString 386 if FileDepex != None: 387 ScheduleList.insert.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0]) 388 else: 389 ScheduleList[FfsID] = NewFfs 390 else: 391 self.UnDispatchedFfsDict[FfsID].Depex = DepexString 392 393 for FfsID in ScheduleList: 394 NewFfs = ScheduleList.pop(FfsID) 395 FfsName = 'UnKnown' 396 self.OrderedFfsDict[FfsID] = NewFfs 397 self.LoadProtocol(Db, FfsID) 398 399 SqlCommand = """select Value2 from Inf 400 where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s) 401 and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001) 402 RecordSet = Db.TblReport.Exec(SqlCommand) 403 if RecordSet != []: 404 FfsName = RecordSet[0][0] 405 406 if IsInstalled: 407 self.DisPatchDxe(Db) 408 409 def DisPatchPei(self, Db): 410 IsInstalled = False 411 for FfsID in self.UnDispatchedFfsDict: 412 CouldBeLoaded = True 413 DepexString = '' 414 FileDepex = None 415 Ffs = self.UnDispatchedFfsDict[FfsID] 416 if Ffs.Type == 0x06 or Ffs.Type == 0x08: 417 # Get Depex 418 for Section in Ffs.Sections.values(): 419 if Section.Type == 0x1B: 420 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi') 421 break 422 423 if Section.Type == 0x01: 424 CompressSections = Section._SubImages[4] 425 for CompressSection in CompressSections.Sections: 426 if CompressSection.Type == 0x1B: 427 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi') 428 break 429 if CompressSection.Type == 0x02: 430 NewSections = CompressSection._SubImages[4] 431 for NewSection in NewSections.Sections: 432 if NewSection.Type == 0x1B: 433 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi') 434 break 435 436 # Append New Ffs 437 if CouldBeLoaded: 438 IsInstalled = True 439 NewFfs = self.UnDispatchedFfsDict.pop(FfsID) 440 NewFfs.Depex = DepexString 441 self.OrderedFfsDict[FfsID] = NewFfs 442 self.LoadPpi(Db, FfsID) 443 else: 444 self.UnDispatchedFfsDict[FfsID].Depex = DepexString 445 446 if IsInstalled: 447 self.DisPatchPei(Db) 448 449 450 def __str__(self): 451 global gIndention 452 gIndention += 4 453 FvInfo = '\n' + ' ' * gIndention 454 FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum) 455 FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict]) 456 gIndention -= 4 457 return FvInfo + FfsInfo 458 459 def _Unpack(self): 460 Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0] 461 self.empty() 462 self.extend(self._BUF_[self._OFF_:self._OFF_+Size]) 463 464 # traverse the FFS 465 EndOfFv = Size 466 FfsStartAddress = self.HeaderSize 467 LastFfsObj = None 468 while FfsStartAddress < EndOfFv: 469 FfsObj = Ffs() 470 FfsObj.frombuffer(self, FfsStartAddress) 471 FfsId = repr(FfsObj) 472 if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \ 473 or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0): 474 if LastFfsObj != None: 475 LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj) 476 else: 477 if FfsId in self.FfsDict: 478 EdkLogger.error("FV", 0, "Duplicate GUID in FFS", 479 ExtraData="\t%s @ %s\n\t%s @ %s" \ 480 % (FfsObj.Guid, FfsObj.Offset, 481 self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset)) 482 self.FfsDict[FfsId] = FfsObj 483 if LastFfsObj != None: 484 LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj) 485 486 FfsStartAddress += len(FfsObj) 487 # 488 # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1)) 489 # The next FFS must be at the latest next 8-byte aligned address 490 # 491 FfsStartAddress = (FfsStartAddress + 7) & (~7) 492 LastFfsObj = FfsObj 493 494 def _GetAttributes(self): 495 return self.GetField(self._ATTR_, 0)[0] 496 497 def _GetSize(self): 498 return self.GetField(self._LENGTH_, 0)[0] 499 500 def _GetChecksum(self): 501 return self.GetField(self._CHECKSUM_, 0)[0] 502 503 def _GetHeaderLength(self): 504 return self.GetField(self._HLEN_, 0)[0] 505 506 def _GetFileSystemGuid(self): 507 return gGuidStringFormat % self.GetField(self._GUID_, 0) 508 509 Attributes = property(_GetAttributes) 510 Size = property(_GetSize) 511 Checksum = property(_GetChecksum) 512 HeaderSize = property(_GetHeaderLength) 513 FileSystemGuid = property(_GetFileSystemGuid) 514 515## CompressedImage() class 516# 517# A class for Compressed Image 518# 519class CompressedImage(Image): 520 # UncompressedLength = 4-byte 521 # CompressionType = 1-byte 522 _HEADER_ = struct.Struct("1I 1B") 523 _HEADER_SIZE_ = _HEADER_.size 524 525 _ORIG_SIZE_ = struct.Struct("1I") 526 _CMPRS_TYPE_ = struct.Struct("4x 1B") 527 528 def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None): 529 Image.__init__(m) 530 if UncompressedLength != None: 531 m.UncompressedLength = UncompressedLength 532 if CompressionType != None: 533 m.CompressionType = CompressionType 534 if CompressedData != None: 535 m.Data = CompressedData 536 537 def __str__(m): 538 global gIndention 539 S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength) 540 for Sec in m.Sections: 541 S += '\n' + str(Sec) 542 543 return S 544 545 def _SetOriginalSize(m, Size): 546 m.SetField(m._ORIG_SIZE_, 0, Size) 547 548 def _GetOriginalSize(m): 549 return m.GetField(m._ORIG_SIZE_)[0] 550 551 def _SetCompressionType(m, Type): 552 m.SetField(m._CMPRS_TYPE_, 0, Type) 553 554 def _GetCompressionType(m): 555 return m.GetField(m._CMPRS_TYPE_)[0] 556 557 def _GetSections(m): 558 try: 559 import EfiCompressor 560 TmpData = EfiCompressor.FrameworkDecompress( 561 m[m._HEADER_SIZE_:], 562 len(m) - m._HEADER_SIZE_ 563 ) 564 DecData = array('B') 565 DecData.fromstring(TmpData) 566 except: 567 import EfiCompressor 568 TmpData = EfiCompressor.UefiDecompress( 569 m[m._HEADER_SIZE_:], 570 len(m) - m._HEADER_SIZE_ 571 ) 572 DecData = array('B') 573 DecData.fromstring(TmpData) 574 575 SectionList = [] 576 Offset = 0 577 while Offset < len(DecData): 578 Sec = Section() 579 try: 580 Sec.frombuffer(DecData, Offset) 581 Offset += Sec.Size 582 # the section is aligned to 4-byte boundary 583 except: 584 break 585 SectionList.append(Sec) 586 return SectionList 587 588 UncompressedLength = property(_GetOriginalSize, _SetOriginalSize) 589 CompressionType = property(_GetCompressionType, _SetCompressionType) 590 Sections = property(_GetSections) 591 592## GuidDefinedImage() class 593# 594# A class for GUID Defined Image 595# 596class GuidDefinedImage(Image): 597 _HEADER_ = struct.Struct("1I2H8B 1H 1H") 598 _HEADER_SIZE_ = _HEADER_.size 599 600 _GUID_ = struct.Struct("1I2H8B") 601 _DATA_OFFSET_ = struct.Struct("16x 1H") 602 _ATTR_ = struct.Struct("18x 1H") 603 604 CRC32_GUID = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083" 605 TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779' 606 LZMA_COMPRESS_GUID = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF' 607 608 def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None): 609 Image.__init__(m) 610 if SectionDefinitionGuid != None: 611 m.SectionDefinitionGuid = SectionDefinitionGuid 612 if DataOffset != None: 613 m.DataOffset = DataOffset 614 if Attributes != None: 615 m.Attributes = Attributes 616 if Data != None: 617 m.Data = Data 618 619 def __str__(m): 620 S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid) 621 for Sec in m.Sections: 622 S += "\n" + str(Sec) 623 return S 624 625 def _Unpack(m): 626 # keep header in this Image object 627 m.empty() 628 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_]) 629 return len(m) 630 631 def _SetAttribute(m, Attribute): 632 m.SetField(m._ATTR_, 0, Attribute) 633 634 def _GetAttribute(m): 635 return m.GetField(m._ATTR_)[0] 636 637 def _SetGuid(m, Guid): 638 m.SetField(m._GUID_, 0, Guid) 639 640 def _GetGuid(m): 641 return m.GetField(m._GUID_) 642 643 def _SetDataOffset(m, Offset): 644 m.SetField(m._DATA_OFFSET_, 0, Offset) 645 646 def _GetDataOffset(m): 647 return m.GetField(m._DATA_OFFSET_)[0] 648 649 def _GetSections(m): 650 SectionList = [] 651 Guid = gGuidStringFormat % m.SectionDefinitionGuid 652 if Guid == m.CRC32_GUID: 653 # skip the CRC32 value, we don't do CRC32 verification here 654 Offset = m.DataOffset - 4 655 while Offset < len(m): 656 Sec = Section() 657 try: 658 Sec.frombuffer(m, Offset) 659 Offset += Sec.Size 660 # the section is aligned to 4-byte boundary 661 Offset = (Offset + 3) & (~3) 662 except: 663 break 664 SectionList.append(Sec) 665 elif Guid == m.TIANO_COMPRESS_GUID: 666 try: 667 import EfiCompressor 668 # skip the header 669 Offset = m.DataOffset - 4 670 TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset) 671 DecData = array('B') 672 DecData.fromstring(TmpData) 673 Offset = 0 674 while Offset < len(DecData): 675 Sec = Section() 676 try: 677 Sec.frombuffer(DecData, Offset) 678 Offset += Sec.Size 679 # the section is aligned to 4-byte boundary 680 Offset = (Offset + 3) & (~3) 681 except: 682 break 683 SectionList.append(Sec) 684 except: 685 pass 686 elif Guid == m.LZMA_COMPRESS_GUID: 687 try: 688 import LzmaCompressor 689 # skip the header 690 Offset = m.DataOffset - 4 691 TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset) 692 DecData = array('B') 693 DecData.fromstring(TmpData) 694 Offset = 0 695 while Offset < len(DecData): 696 Sec = Section() 697 try: 698 Sec.frombuffer(DecData, Offset) 699 Offset += Sec.Size 700 # the section is aligned to 4-byte boundary 701 Offset = (Offset + 3) & (~3) 702 except: 703 break 704 SectionList.append(Sec) 705 except: 706 pass 707 708 return SectionList 709 710 Attributes = property(_GetAttribute, _SetAttribute) 711 SectionDefinitionGuid = property(_GetGuid, _SetGuid) 712 DataOffset = property(_GetDataOffset, _SetDataOffset) 713 Sections = property(_GetSections) 714 715## Depex() class 716# 717# A class for Depex 718# 719class Depex(Image): 720 _HEADER_ = struct.Struct("") 721 _HEADER_SIZE_ = 0 722 723 _GUID_ = struct.Struct("1I2H8B") 724 _OPCODE_ = struct.Struct("1B") 725 726 _OPCODE_STRING_ = { 727 0x00 : "BEFORE", 728 0x01 : "AFTER", 729 0x02 : "PUSH", 730 0x03 : "AND", 731 0x04 : "OR", 732 0x05 : "NOT", 733 0x06 : "TRUE", 734 0x07 : "FALSE", 735 0x08 : "END", 736 0x09 : "SOR" 737 } 738 739 _NEXT_ = { 740 -1 : _OPCODE_, # first one in depex must be an opcdoe 741 0x00 : _GUID_, #"BEFORE", 742 0x01 : _GUID_, #"AFTER", 743 0x02 : _GUID_, #"PUSH", 744 0x03 : _OPCODE_, #"AND", 745 0x04 : _OPCODE_, #"OR", 746 0x05 : _OPCODE_, #"NOT", 747 0x06 : _OPCODE_, #"TRUE", 748 0x07 : _OPCODE_, #"FALSE", 749 0x08 : None, #"END", 750 0x09 : _OPCODE_, #"SOR" 751 } 752 753 def __init__(m): 754 Image.__init__(m) 755 m._ExprList = [] 756 757 def __str__(m): 758 global gIndention 759 gIndention += 4 760 Indention = ' ' * gIndention 761 S = '\n' 762 for T in m.Expression: 763 if T in m._OPCODE_STRING_: 764 S += Indention + m._OPCODE_STRING_[T] 765 if T not in [0x00, 0x01, 0x02]: 766 S += '\n' 767 else: 768 S += ' ' + gGuidStringFormat % T + '\n' 769 gIndention -= 4 770 return S 771 772 def _Unpack(m): 773 # keep header in this Image object 774 m.empty() 775 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_]) 776 return len(m) 777 778 def _GetExpression(m): 779 if m._ExprList == []: 780 Offset = 0 781 CurrentData = m._OPCODE_ 782 while Offset < len(m): 783 Token = CurrentData.unpack_from(m, Offset) 784 Offset += CurrentData.size 785 if len(Token) == 1: 786 Token = Token[0] 787 if Token in m._NEXT_: 788 CurrentData = m._NEXT_[Token] 789 else: 790 CurrentData = m._GUID_ 791 else: 792 CurrentData = m._OPCODE_ 793 m._ExprList.append(Token) 794 if CurrentData == None: 795 break 796 return m._ExprList 797 798 Expression = property(_GetExpression) 799 800## Ui() class 801# 802# A class for Ui 803# 804class Ui(Image): 805 _HEADER_ = struct.Struct("") 806 _HEADER_SIZE_ = 0 807 808 def __init__(m): 809 Image.__init__(m) 810 811 def __str__(m): 812 return m.String 813 814 def _Unpack(m): 815 # keep header in this Image object 816 m.empty() 817 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_]) 818 return len(m) 819 820 def _GetUiString(m): 821 return codecs.utf_16_decode(m[0:-2].tostring())[0] 822 823 String = property(_GetUiString) 824 825## Section() class 826# 827# A class for Section 828# 829class Section(Image): 830 _TypeName = { 831 0x00 : "<unknown>", 832 0x01 : "COMPRESSION", 833 0x02 : "GUID_DEFINED", 834 0x10 : "PE32", 835 0x11 : "PIC", 836 0x12 : "TE", 837 0x13 : "DXE_DEPEX", 838 0x14 : "VERSION", 839 0x15 : "USER_INTERFACE", 840 0x16 : "COMPATIBILITY16", 841 0x17 : "FIRMWARE_VOLUME_IMAGE", 842 0x18 : "FREEFORM_SUBTYPE_GUID", 843 0x19 : "RAW", 844 0x1B : "PEI_DEPEX" 845 } 846 847 _SectionSubImages = { 848 0x01 : CompressedImage, 849 0x02 : GuidDefinedImage, 850 0x17 : FirmwareVolume, 851 0x13 : Depex, 852 0x1B : Depex, 853 0x15 : Ui 854 } 855 856 # Size = 3-byte 857 # Type = 1-byte 858 _HEADER_ = struct.Struct("3B 1B") 859 _HEADER_SIZE_ = _HEADER_.size 860 861 # SubTypeGuid 862 # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B") 863 864 _SIZE_ = struct.Struct("3B") 865 _TYPE_ = struct.Struct("3x 1B") 866 867 def __init__(m, Type=None, Size=None): 868 Image.__init__(m) 869 m._Alignment = 1 870 if Type != None: 871 m.Type = Type 872 if Size != None: 873 m.Size = Size 874 875 def __str__(m): 876 global gIndention 877 gIndention += 4 878 SectionInfo = ' ' * gIndention 879 if m.Type in m._TypeName: 880 SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size) 881 else: 882 SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size) 883 for Offset in m._SubImages: 884 SectionInfo += ", " + str(m._SubImages[Offset]) 885 gIndention -= 4 886 return SectionInfo 887 888 def _Unpack(m): 889 m.empty() 890 Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_) 891 Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_) 892 Size = Size1 + (Size2 << 8) + (Size3 << 16) 893 894 if Type not in m._SectionSubImages: 895 # no need to extract sub-image, keep all in this Image object 896 m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size]) 897 else: 898 # keep header in this Image object 899 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_]) 900 # 901 # use new Image object to represent payload, which may be another kind 902 # of image such as PE32 903 # 904 PayloadOffset = m._HEADER_SIZE_ 905 PayloadLen = m.Size - m._HEADER_SIZE_ 906 Payload = m._SectionSubImages[m.Type]() 907 Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen) 908 m._SubImages[PayloadOffset] = Payload 909 910 return Size 911 912 def _SetSize(m, Size): 913 Size1 = Size & 0xFF 914 Size2 = (Size & 0xFF00) >> 8 915 Size3 = (Size & 0xFF0000) >> 16 916 m.SetField(m._SIZE_, 0, Size1, Size2, Size3) 917 918 def _GetSize(m): 919 Size1, Size2, Size3 = m.GetField(m._SIZE_) 920 return Size1 + (Size2 << 8) + (Size3 << 16) 921 922 def _SetType(m, Type): 923 m.SetField(m._TYPE_, 0, Type) 924 925 def _GetType(m): 926 return m.GetField(m._TYPE_)[0] 927 928 def _GetAlignment(m): 929 return m._Alignment 930 931 def _SetAlignment(m, Alignment): 932 m._Alignment = Alignment 933 AlignmentMask = Alignment - 1 934 # section alignment is actually for payload, so we need to add header size 935 PayloadOffset = m._OFF_ + m._HEADER_SIZE_ 936 if (PayloadOffset & (~AlignmentMask)) == 0: 937 return 938 NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask) 939 while (NewOffset - PayloadOffset) < m._HEADER_SIZE_: 940 NewOffset += m._Alignment 941 942 def tofile(m, f): 943 m.Size = len(m) 944 Image.tofile(m, f) 945 for Offset in m._SubImages: 946 m._SubImages[Offset].tofile(f) 947 948 Type = property(_GetType, _SetType) 949 Size = property(_GetSize, _SetSize) 950 Alignment = property(_GetAlignment, _SetAlignment) 951 # SubTypeGuid = property(_GetGuid, _SetGuid) 952 953## PadSection() class 954# 955# A class for Pad Section 956# 957class PadSection(Section): 958 def __init__(m, Size): 959 Section.__init__(m) 960 m.Type = 0x19 961 m.Size = Size 962 m.Data = [0] * (Size - m._HEADER_SIZE_) 963 964## Ffs() class 965# 966# A class for Ffs Section 967# 968class Ffs(Image): 969 _FfsFormat = "24B%(payload_size)sB" 970 # skip IntegrityCheck 971 _HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B") 972 _HEADER_SIZE_ = _HEADER_.size 973 974 _NAME_ = struct.Struct("1I2H8B") 975 _INT_CHECK_ = struct.Struct("16x 1H") 976 _TYPE_ = struct.Struct("18x 1B") 977 _ATTR_ = struct.Struct("19x 1B") 978 _SIZE_ = struct.Struct("20x 3B") 979 _STATE_ = struct.Struct("23x 1B") 980 981 VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09" 982 983 FFS_ATTRIB_FIXED = 0x04 984 FFS_ATTRIB_DATA_ALIGNMENT = 0x38 985 FFS_ATTRIB_CHECKSUM = 0x40 986 987 _TypeName = { 988 0x00 : "<unknown>", 989 0x01 : "RAW", 990 0x02 : "FREEFORM", 991 0x03 : "SECURITY_CORE", 992 0x04 : "PEI_CORE", 993 0x05 : "DXE_CORE", 994 0x06 : "PEIM", 995 0x07 : "DRIVER", 996 0x08 : "COMBINED_PEIM_DRIVER", 997 0x09 : "APPLICATION", 998 0x0A : "SMM", 999 0x0B : "FIRMWARE_VOLUME_IMAGE", 1000 0x0C : "COMBINED_SMM_DXE", 1001 0x0D : "SMM_CORE", 1002 0xc0 : "OEM_MIN", 1003 0xdf : "OEM_MAX", 1004 0xe0 : "DEBUG_MIN", 1005 0xef : "DEBUG_MAX", 1006 0xf0 : "FFS_MIN", 1007 0xff : "FFS_MAX", 1008 0xf0 : "FFS_PAD", 1009 } 1010 1011 def __init__(self): 1012 Image.__init__(self) 1013 self.FreeSpace = 0 1014 1015 self.Sections = sdict() 1016 self.Depex = '' 1017 1018 self.__ID__ = None 1019 1020 def __str__(self): 1021 global gIndention 1022 gIndention += 4 1023 Indention = ' ' * gIndention 1024 FfsInfo = Indention 1025 FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \ 1026 (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment) 1027 SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections]) 1028 gIndention -= 4 1029 return FfsInfo + SectionInfo + "\n" 1030 1031 def __len__(self): 1032 return self.Size 1033 1034 def __repr__(self): 1035 return self.__ID__ 1036 1037 def _Unpack(self): 1038 Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_) 1039 Size = Size1 + (Size2 << 8) + (Size3 << 16) 1040 self.empty() 1041 self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size]) 1042 1043 # Pad FFS may use the same GUID. We need to avoid it. 1044 if self.Type == 0xf0: 1045 self.__ID__ = str(uuid.uuid1()).upper() 1046 else: 1047 self.__ID__ = self.Guid 1048 1049 # Traverse the SECTION. RAW and PAD do not have sections 1050 if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF: 1051 EndOfFfs = Size 1052 SectionStartAddress = self._HEADER_SIZE_ 1053 while SectionStartAddress < EndOfFfs: 1054 SectionObj = Section() 1055 SectionObj.frombuffer(self, SectionStartAddress) 1056 #f = open(repr(SectionObj), 'wb') 1057 #SectionObj.Size = 0 1058 #SectionObj.tofile(f) 1059 #f.close() 1060 self.Sections[SectionStartAddress] = SectionObj 1061 SectionStartAddress += len(SectionObj) 1062 SectionStartAddress = (SectionStartAddress + 3) & (~3) 1063 1064 def Pack(self): 1065 pass 1066 1067 def SetFreeSpace(self, Size): 1068 self.FreeSpace = Size 1069 1070 def _GetGuid(self): 1071 return gGuidStringFormat % self.Name 1072 1073 def _SetName(self, Value): 1074 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11 1075 self.SetField(self._NAME_, 0, Value) 1076 1077 def _GetName(self): 1078 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11 1079 return self.GetField(self._NAME_) 1080 1081 def _SetSize(m, Size): 1082 Size1 = Size & 0xFF 1083 Size2 = (Size & 0xFF00) >> 8 1084 Size3 = (Size & 0xFF0000) >> 16 1085 m.SetField(m._SIZE_, 0, Size1, Size2, Size3) 1086 1087 def _GetSize(m): 1088 Size1, Size2, Size3 = m.GetField(m._SIZE_) 1089 return Size1 + (Size2 << 8) + (Size3 << 16) 1090 1091 def _SetType(m, Type): 1092 m.SetField(m._TYPE_, 0, Type) 1093 1094 def _GetType(m): 1095 return m.GetField(m._TYPE_)[0] 1096 1097 def _SetAttributes(self, Value): 1098 self.SetField(m._ATTR_, 0, Value) 1099 1100 def _GetAttributes(self): 1101 return self.GetField(self._ATTR_)[0] 1102 1103 def _GetFixed(self): 1104 if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0: 1105 return True 1106 return False 1107 1108 def _GetCheckSum(self): 1109 if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0: 1110 return True 1111 return False 1112 1113 def _GetAlignment(self): 1114 return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3 1115 1116 def _SetState(self, Value): 1117 self.SetField(m._STATE_, 0, Value) 1118 1119 def _GetState(self): 1120 return self.GetField(m._STATE_)[0] 1121 1122 Name = property(_GetName, _SetName) 1123 Guid = property(_GetGuid) 1124 Type = property(_GetType, _SetType) 1125 Size = property(_GetSize, _SetSize) 1126 Attributes = property(_GetAttributes, _SetAttributes) 1127 Fixed = property(_GetFixed) 1128 Checksum = property(_GetCheckSum) 1129 Alignment = property(_GetAlignment) 1130 State = property(_GetState, _SetState) 1131 1132## PeImage() class 1133# 1134# A class for PE Image 1135# 1136class PeImage: 1137 # 1138 # just extract e_lfanew 1139 # 1140 _DosHeaderFormat = "60x 1I" 1141 # 1142 # Machine 1143 # NumberOfSections 1144 # SizeOfOptionalHeader 1145 # 1146 _FileHeaderFormat = "4x 1H 1H 4x 4x 4x 1H 2x" 1147 # 1148 # Magic 1149 # SizeOfImage 1150 # SizeOfHeaders 1151 # CheckSum 1152 # NumberOfRvaAndSizes 1153 # 1154 _OptionalHeader32Format = "1H 54x 1I 1I 1I 24x 1I" 1155 _OptionalHeader64Format = "" 1156 def __init__(self, Buf, Offset, Size): 1157 self.Offset = Offset 1158 self.Size = Size 1159 self.Machine = 0x014c # IA32 1160 self.NumberOfSections = 0 1161 self.SizeOfImage = 0 1162 self.SizeOfOptionalHeader = 0 1163 self.Checksum = 0 1164 self._PeImageBuf = Buf 1165 self._SectionList = [] 1166 1167 self._DosHeader = struct.Struct(PeImage._DosHeaderFormat) 1168 self._FileHeader = struct.Struct(PeImage._FileHeaderFormat) 1169 self._OptionalHeader32 = struct.Struct(PeImage._OptionalHeader32Format) 1170 1171 self.Buffer = None 1172 1173 self._Unpack() 1174 1175 def __str__(self): 1176 pass 1177 1178 def __len__(self): 1179 return self.Size 1180 1181 def _Unpack(self): 1182 # from DOS header, get the offset of PE header 1183 FileHeaderOffset, = self._DosHeader.unpack_from(self._PeImageBuf, self.Offset) 1184 if FileHeaderOffset < struct.calcsize(self._DosHeaderFormat): 1185 EdkLogger.error("PE+", 0, "Invalid offset of IMAGE_FILE_HEADER: %s" % FileHeaderOffset) 1186 1187 # from FILE header, get the optional header size 1188 self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader = \ 1189 self._FileHeader.unpack_from(self._PeImageBuf, self.Offset + FileHeaderOffset) 1190 1191 print "Machine=%x NumberOfSections=%x SizeOfOptionalHeader=%x" % (self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader) 1192 # optional header follows the FILE header 1193 OptionalHeaderOffset = FileHeaderOffset + struct.calcsize(self._FileHeaderFormat) 1194 Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes = \ 1195 self._OptionalHeader32.unpack_from(self._PeImageBuf, self.Offset + OptionalHeaderOffset) 1196 print "Magic=%x SizeOfImage=%x SizeOfHeaders=%x, Checksum=%x, NumberOfRvaAndSizes=%x" % (Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes) 1197 1198 PeImageSectionTableOffset = OptionalHeaderOffset + self.SizeOfOptionalHeader 1199 PeSections = PeSectionTable(self._PeImageBuf, self.Offset + PeImageSectionTableOffset, self.NumberOfSections) 1200 1201 print "%x" % PeSections.GetFileAddress(0x3920) 1202 1203## PeSectionTable() class 1204# 1205# A class for PE Section Table 1206# 1207class PeSectionTable: 1208 def __init__(self, Buf, Offset, NumberOfSections): 1209 self._SectionList = [] 1210 1211 SectionHeaderOffset = Offset 1212 for TableIndex in range(0, NumberOfSections): 1213 SectionHeader = PeSectionHeader(Buf, SectionHeaderOffset) 1214 self._SectionList.append(SectionHeader) 1215 SectionHeaderOffset += len(SectionHeader) 1216 print SectionHeader 1217 1218 def GetFileAddress(self, Rva): 1219 for PeSection in self._SectionList: 1220 if Rva in PeSection: 1221 return PeSection[Rva] 1222 1223## PeSectionHeader() class 1224# 1225# A class for PE Section Header 1226# 1227class PeSectionHeader: 1228 # 1229 # VirtualAddress 1230 # SizeOfRawData 1231 # PointerToRawData 1232 # 1233 _HeaderFormat = "12x 1I 1I 1I 16x" 1234 _HeaderLength = struct.calcsize(_HeaderFormat) 1235 1236 def __init__(self, Buf, Offset): 1237 self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData = \ 1238 struct.unpack_from(self._HeaderFormat, Buf, Offset) 1239 self.VirtualAddressEnd = self.VirtualAddressStart + self.SizeOfRawData - 1 1240 1241 def __str__(self): 1242 return "VirtualAddress=%x, SizeOfRawData=%x, PointerToRawData=%x" % (self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData) 1243 1244 def __len__(self): 1245 return self._HeaderLength 1246 1247 def __contains__(self, Rva): 1248 return Rva >= self.VirtualAddressStart and Rva <= self.VirtualAddressEnd 1249 1250 def __getitem__(self, Rva): 1251 return Rva - self.VirtualAddressStart + self.PointerToRawData 1252 1253## LinkMap() class 1254# 1255# A class for Link Map 1256# 1257class LinkMap: 1258 _StartFlag = { 1259 "MSFT" : re.compile("Address +Publics by Value +Rva\+Base +Lib:Object"), 1260 "GCC" : re.compile("^\.(text|bss|data|edata)"), 1261 } 1262 1263 _MappingFormat = { 1264 "MSFT" : re.compile("([0-9a-f]+):([0-9a-f]+)\s+_+([0-9A-Za-z]+)\s+([0-9a-f]+)\s+"), 1265 "GCC" : re.compile("^(\.\w)?\s+(0x[0-9a-f]+)\s+_+([0-9A-Za-z]+)"), 1266 } 1267 1268 def __init__(self, MapFile, MapType="MSFT"): 1269 self.File = MapFile 1270 self.MapType = MapType 1271 self._Globals = {} # global:RVA 1272 1273 self._Parse() 1274 1275 def _Parse(self): 1276 MapFile = open(self.File, 'r') 1277 MappingTitle = self._StartFlag[self.MapType] 1278 MappingFormat = self._MappingFormat[self.MapType] 1279 MappingStart = False 1280 try: 1281 for Line in MapFile: 1282 Line = Line.strip() 1283 if not MappingStart: 1284 if MappingTitle.match(Line) != None: 1285 MappingStart = True 1286 continue 1287 ResultList = MappingFormat.findall(Line) 1288 if len(ResultList) == 0 or len(ResultList[0]) != 4: 1289 continue 1290 self._Globals[ResultList[2]] = int(ResultList[3], 16) 1291 EdkLogger.verbose(ResultList[0]) 1292 finally: 1293 MapFile.close() 1294 1295 def __contains__(self, Var): 1296 return Var in self._Globals 1297 1298 def __getitem__(self, Var): 1299 if Var not in self._Globals: 1300 return None 1301 return self._Globals[Var] 1302 1303## MultipleFv() class 1304# 1305# A class for Multiple FV 1306# 1307class MultipleFv(FirmwareVolume): 1308 def __init__(self, FvList): 1309 FirmwareVolume.__init__(self) 1310 self.BasicInfo = [] 1311 for FvPath in FvList: 1312 FvName = os.path.splitext(os.path.split(FvPath)[1])[0] 1313 Fd = open(FvPath, 'rb') 1314 Buf = array('B') 1315 try: 1316 Buf.fromfile(Fd, os.path.getsize(FvPath)) 1317 except EOFError: 1318 pass 1319 1320 Fv = FirmwareVolume(FvName) 1321 Fv.frombuffer(Buf, 0, len(Buf)) 1322 1323 self.BasicInfo.append([Fv.Name, Fv.FileSystemGuid, Fv.Size]) 1324 self.FfsDict.append(Fv.FfsDict) 1325 1326# Version and Copyright 1327__version_number__ = "0.01" 1328__version__ = "%prog Version " + __version_number__ 1329__copyright__ = "Copyright (c) 2008, Intel Corporation. All rights reserved." 1330 1331## Parse command line options 1332# 1333# Using standard Python module optparse to parse command line option of this tool. 1334# 1335# @retval Options A optparse.Values object containing the parsed options 1336# @retval InputFile Path of file to be trimmed 1337# 1338def GetOptions(): 1339 OptionList = [ 1340 make_option("-a", "--arch", dest="Arch", 1341 help="The input file is preprocessed source code, including C or assembly code"), 1342 make_option("-p", "--platform", dest="ActivePlatform", 1343 help="The input file is preprocessed VFR file"), 1344 make_option("-m", "--module", dest="ActiveModule", 1345 help="Convert standard hex format (0xabcd) to MASM format (abcdh)"), 1346 make_option("-f", "--FDF-file", dest="FdfFile", 1347 help="Convert standard hex format (0xabcd) to MASM format (abcdh)"), 1348 make_option("-o", "--output", dest="OutputDirectory", 1349 help="File to store the trimmed content"), 1350 make_option("-t", "--toolchain-tag", dest="ToolChain", 1351 help=""), 1352 make_option("-k", "--msft", dest="MakefileType", action="store_const", const="nmake", 1353 help=""), 1354 make_option("-g", "--gcc", dest="MakefileType", action="store_const", const="gmake", 1355 help=""), 1356 make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE, 1357 help="Run verbosely"), 1358 make_option("-d", "--debug", dest="LogLevel", type="int", 1359 help="Run with debug information"), 1360 make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET, 1361 help="Run quietly"), 1362 make_option("-?", action="help", help="show this help message and exit"), 1363 ] 1364 1365 # use clearer usage to override default usage message 1366 UsageString = "%prog [-a ARCH] [-p PLATFORM] [-m MODULE] [-t TOOLCHAIN_TAG] [-k] [-g] [-v|-d <debug_level>|-q] [-o <output_directory>] [GenC|GenMake]" 1367 1368 Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString) 1369 Parser.set_defaults(Arch=[]) 1370 Parser.set_defaults(ActivePlatform=None) 1371 Parser.set_defaults(ActiveModule=None) 1372 Parser.set_defaults(OutputDirectory="build") 1373 Parser.set_defaults(FdfFile=None) 1374 Parser.set_defaults(ToolChain="MYTOOLS") 1375 if sys.platform == "win32": 1376 Parser.set_defaults(MakefileType="nmake") 1377 else: 1378 Parser.set_defaults(MakefileType="gmake") 1379 Parser.set_defaults(LogLevel=EdkLogger.INFO) 1380 1381 Options, Args = Parser.parse_args() 1382 1383 # error check 1384 if len(Args) == 0: 1385 Options.Target = "genmake" 1386 sys.argv.append("genmake") 1387 elif len(Args) == 1: 1388 Options.Target = Args[0].lower() 1389 if Options.Target not in ["genc", "genmake"]: 1390 EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Not supported target", 1391 ExtraData="%s\n\n%s" % (Options.Target, Parser.get_usage())) 1392 else: 1393 EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Too many targets", 1394 ExtraData=Parser.get_usage()) 1395 1396 return Options 1397 1398## Entrance method 1399# 1400# This method mainly dispatch specific methods per the command line options. 1401# If no error found, return zero value so the caller of this tool can know 1402# if it's executed successfully or not. 1403# 1404# @retval 0 Tool was successful 1405# @retval 1 Tool failed 1406# 1407def Main(): 1408 from build import build 1409 try: 1410 Option = GetOptions() 1411 build.main() 1412 except Exception, e: 1413 print e 1414 return 1 1415 1416 return 0 1417 1418# This acts like the main() function for the script, unless it is 'import'ed into another script. 1419if __name__ == '__main__': 1420 EdkLogger.Initialize() 1421 # sys.exit(Main()) 1422 1423 if len(sys.argv) > 1: 1424 FilePath = sys.argv[1] 1425 if FilePath.lower().endswith(".fv"): 1426 fd = open(FilePath, 'rb') 1427 buf = array('B') 1428 try: 1429 buf.fromfile(fd, os.path.getsize(FilePath)) 1430 except EOFError: 1431 pass 1432 1433 fv = FirmwareVolume("FVRECOVERY") 1434 fv.frombuffer(buf, 0, len(buf)) 1435 #fv.Dispatch(None) 1436 print fv 1437 elif FilePath.endswith(".efi"): 1438 fd = open(FilePath, 'rb') 1439 buf = array('B') 1440 Size = os.path.getsize(FilePath) 1441 1442 try: 1443 buf.fromfile(fd, Size) 1444 except EOFError: 1445 pass 1446 1447 PeSection = Section(Type=0x10) 1448 PeSection.Data = buf 1449 sf, ext = os.path.splitext(os.path.basename(FilePath)) 1450 sf += ".sec" 1451 PeSection.tofile(open(sf, 'wb')) 1452 elif FilePath.endswith(".map"): 1453 mf = LinkMap(FilePath) 1454