Home | History | Annotate | Download | only in Eot
      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 #

     16 import Common.LongFilePathOs as os
     17 import re
     18 import sys
     19 import uuid
     20 import struct
     21 import codecs
     22 import copy
     23 
     24 from UserDict import IterableUserDict
     25 from cStringIO import StringIO
     26 from array import array
     27 from Common.LongFilePathSupport import OpenLongFilePath as open
     28 from CommonDataClass import *
     29 from Common.Misc import sdict, GuidStructureStringToGuidString
     30 
     31 import Common.EdkLogger as EdkLogger
     32 
     33 import EotGlobalData
     34 
     35 # Global definiton

     36 gFfsPrintTitle  = "%-36s  %-21s %8s %8s %8s  %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME")
     37 gFfsPrintFormat = "%36s  %-21s %8X %8X %8X  %4s %-36s"
     38 gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
     39 gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'
     40 gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'
     41 gIndention = -4
     42 
     43 ## Image() class

     44 #

     45 #  A class for Image

     46 #

     47 class 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 #

    121 class 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 #

    519 class 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 #

    596 class 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 #

    719 class 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 #

    804 class 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 #

    829 class 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 #

    957 class 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 #

    968 class 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 #

   1136 class 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 #

   1207 class 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 #

   1227 class 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 #

   1257 class 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 #

   1307 class 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 #

   1338 def 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 #

   1407 def 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.

   1419 if __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