audk/BaseTools/Source/Python/Eot/FvImage.py

1454 lines
52 KiB
Python

## @file
# Parse FV image
#
# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
## Import Modules
#
import Common.LongFilePathOs as os
import re
import sys
import uuid
import struct
import codecs
import copy
from UserDict import IterableUserDict
from cStringIO import StringIO
from array import array
from Common.LongFilePathSupport import OpenLongFilePath as open
from CommonDataClass import *
from Common.Misc import sdict, GuidStructureStringToGuidString
import Common.EdkLogger as EdkLogger
import EotGlobalData
# Global definiton
gFfsPrintTitle = "%-36s %-21s %8s %8s %8s %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME")
gFfsPrintFormat = "%36s %-21s %8X %8X %8X %4s %-36s"
gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'
gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'
gIndention = -4
## Image() class
#
# A class for Image
#
class Image(array):
_HEADER_ = struct.Struct("")
_HEADER_SIZE_ = _HEADER_.size
def __new__(cls, *args, **kwargs):
return array.__new__(cls, 'B')
def __init__(m, ID=None):
if ID == None:
m._ID_ = str(uuid.uuid1()).upper()
else:
m._ID_ = ID
m._BUF_ = None
m._LEN_ = None
m._OFF_ = None
m._SubImages = sdict() # {offset: Image()}
array.__init__(m, 'B')
def __repr__(m):
return m._ID_
def __len__(m):
Len = array.__len__(m)
for Offset in m._SubImages:
Len += len(m._SubImages[Offset])
return Len
def _Unpack(m):
m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
return len(m)
def _Pack(m, PadByte=0xFF):
raise NotImplementedError
def frombuffer(m, Buffer, Offset=0, Size=None):
m._BUF_ = Buffer
m._OFF_ = Offset
# we may need the Size information in advance if it's given
m._LEN_ = Size
m._LEN_ = m._Unpack()
def empty(m):
del m[0:]
def GetField(m, FieldStruct, Offset=0):
return FieldStruct.unpack_from(m, Offset)
def SetField(m, FieldStruct, Offset, *args):
# check if there's enough space
Size = FieldStruct.size
if Size > len(m):
m.extend([0] * (Size - len(m)))
FieldStruct.pack_into(m, Offset, *args)
def _SetData(m, Data):
if len(m) < m._HEADER_SIZE_:
m.extend([0] * (m._HEADER_SIZE_ - len(m)))
else:
del m[m._HEADER_SIZE_:]
m.extend(Data)
def _GetData(m):
if len(m) > m._HEADER_SIZE_:
return m[m._HEADER_SIZE_:]
return None
Data = property(_GetData, _SetData)
## FirmwareVolume() class
#
# A class for Firmware Volume
#
class FirmwareVolume(Image):
# Read FvLength, Attributes, HeaderLength, Checksum
_HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
_HEADER_SIZE_ = _HEADER_.size
_FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
_GUID_ = struct.Struct("16x 1I2H8B")
_LENGTH_ = struct.Struct("16x 16x 1Q")
_SIG_ = struct.Struct("16x 16x 8x 1I")
_ATTR_ = struct.Struct("16x 16x 8x 4x 1I")
_HLEN_ = struct.Struct("16x 16x 8x 4x 4x 1H")
_CHECKSUM_ = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
def __init__(self, Name=''):
Image.__init__(self)
self.Name = Name
self.FfsDict = sdict()
self.OrderedFfsDict = sdict()
self.UnDispatchedFfsDict = sdict()
self.NoDepexFfsDict = sdict()
self.ProtocolList = sdict()
def CheckArchProtocol(self):
for Item in EotGlobalData.gArchProtocolGuids:
if Item.lower() not in EotGlobalData.gProtocolList:
return False
return True
def ParseDepex(self, Depex, Type):
List = None
if Type == 'Ppi':
List = EotGlobalData.gPpiList
if Type == 'Protocol':
List = EotGlobalData.gProtocolList
DepexStack = []
DepexList = []
DepexString = ''
FileDepex = None
CouldBeLoaded = True
for Index in range(0, len(Depex.Expression)):
Item = Depex.Expression[Index]
if Item == 0x00:
Index = Index + 1
Guid = gGuidStringFormat % Depex.Expression[Index]
if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
elif Item == 0x01:
Index = Index + 1
Guid = gGuidStringFormat % Depex.Expression[Index]
if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
elif Item == 0x02:
Index = Index + 1
Guid = gGuidStringFormat % Depex.Expression[Index]
if Guid.lower() in List:
DepexStack.append(True)
DepexList.append(Guid)
else:
DepexStack.append(False)
DepexList.append(Guid)
continue
elif Item == 0x03 or Item == 0x04:
DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
elif Item == 0x05:
DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
elif Item == 0x06:
DepexStack.append(True)
DepexList.append('TRUE')
DepexString = DepexString + 'TRUE' + ' '
elif Item == 0x07:
DepexStack.append(False)
DepexList.append('False')
DepexString = DepexString + 'FALSE' + ' '
elif Item == 0x08:
if Index != len(Depex.Expression) - 1:
CouldBeLoaded = False
else:
CouldBeLoaded = DepexStack.pop()
else:
CouldBeLoaded = False
if DepexList != []:
DepexString = DepexList[0].strip()
return (CouldBeLoaded, DepexString, FileDepex)
def Dispatch(self, Db = None):
if Db == None:
return False
self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
# Find PeiCore, DexCore, PeiPriori, DxePriori first
FfsSecCoreGuid = None
FfsPeiCoreGuid = None
FfsDxeCoreGuid = None
FfsPeiPrioriGuid = None
FfsDxePrioriGuid = None
for FfsID in self.UnDispatchedFfsDict:
Ffs = self.UnDispatchedFfsDict[FfsID]
if Ffs.Type == 0x03:
FfsSecCoreGuid = FfsID
continue
if Ffs.Type == 0x04:
FfsPeiCoreGuid = FfsID
continue
if Ffs.Type == 0x05:
FfsDxeCoreGuid = FfsID
continue
if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
FfsPeiPrioriGuid = FfsID
continue
if Ffs.Guid.lower() == gAprioriGuid:
FfsDxePrioriGuid = FfsID
continue
# Parse SEC_CORE first
if FfsSecCoreGuid != None:
self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
self.LoadPpi(Db, FfsSecCoreGuid)
# Parse PEI first
if FfsPeiCoreGuid != None:
self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
self.LoadPpi(Db, FfsPeiCoreGuid)
if FfsPeiPrioriGuid != None:
# Load PEIM described in priori file
FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
if len(FfsPeiPriori.Sections) == 1:
Section = FfsPeiPriori.Sections.popitem()[1]
if Section.Type == 0x19:
GuidStruct = struct.Struct('1I2H8B')
Start = 4
while len(Section) > Start:
Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
GuidString = gGuidStringFormat % Guid
Start = Start + 16
if GuidString in self.UnDispatchedFfsDict:
self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
self.LoadPpi(Db, GuidString)
self.DisPatchPei(Db)
# Parse DXE then
if FfsDxeCoreGuid != None:
self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
self.LoadProtocol(Db, FfsDxeCoreGuid)
if FfsDxePrioriGuid != None:
# Load PEIM described in priori file
FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
if len(FfsDxePriori.Sections) == 1:
Section = FfsDxePriori.Sections.popitem()[1]
if Section.Type == 0x19:
GuidStruct = struct.Struct('1I2H8B')
Start = 4
while len(Section) > Start:
Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
GuidString = gGuidStringFormat % Guid
Start = Start + 16
if GuidString in self.UnDispatchedFfsDict:
self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
self.LoadProtocol(Db, GuidString)
self.DisPatchDxe(Db)
def DisPatchNoDepexFfs(self, Db):
# Last Load Drivers without Depex
for FfsID in self.NoDepexFfsDict:
NewFfs = self.NoDepexFfsDict.pop(FfsID)
self.OrderedFfsDict[FfsID] = NewFfs
self.LoadProtocol(Db, FfsID)
return True
def LoadCallbackProtocol(self):
IsLoad = True
for Protocol in self.ProtocolList:
for Callback in self.ProtocolList[Protocol][1]:
if Callback[0] not in self.OrderedFfsDict.keys():
IsLoad = False
continue
if IsLoad:
EotGlobalData.gProtocolList[Protocol.lower()] = self.ProtocolList[Protocol][0]
self.ProtocolList.pop(Protocol)
def LoadProtocol(self, Db, ModuleGuid):
SqlCommand = """select GuidValue from Report
where SourceFileFullPath in
(select Value1 from Inf where BelongsToFile =
(select BelongsToFile from Inf
where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
and Model = %s)
and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
% (ModuleGuid, 5001, 3007)
RecordSet = Db.TblReport.Exec(SqlCommand)
for Record in RecordSet:
SqlCommand = """select Value2 from Inf where BelongsToFile =
(select DISTINCT BelongsToFile from Inf
where Value1 =
(select SourceFileFullPath from Report
where GuidValue like '%s' and ItemMode = 'Callback'))
and Value1 = 'FILE_GUID'""" % Record[0]
CallBackSet = Db.TblReport.Exec(SqlCommand)
if CallBackSet != []:
EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
else:
EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
def LoadPpi(self, Db, ModuleGuid):
SqlCommand = """select GuidValue from Report
where SourceFileFullPath in
(select Value1 from Inf where BelongsToFile =
(select BelongsToFile from Inf
where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
and Model = %s)
and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
% (ModuleGuid, 5001, 3007)
RecordSet = Db.TblReport.Exec(SqlCommand)
for Record in RecordSet:
EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
def DisPatchDxe(self, Db):
IsInstalled = False
ScheduleList = sdict()
for FfsID in self.UnDispatchedFfsDict:
CouldBeLoaded = False
DepexString = ''
FileDepex = None
Ffs = self.UnDispatchedFfsDict[FfsID]
if Ffs.Type == 0x07:
# Get Depex
IsFoundDepex = False
for Section in Ffs.Sections.values():
# Find Depex
if Section.Type == 0x13:
IsFoundDepex = True
CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
break
if Section.Type == 0x01:
CompressSections = Section._SubImages[4]
for CompressSection in CompressSections.Sections:
if CompressSection.Type == 0x13:
IsFoundDepex = True
CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
break
if CompressSection.Type == 0x02:
NewSections = CompressSection._SubImages[4]
for NewSection in NewSections.Sections:
if NewSection.Type == 0x13:
IsFoundDepex = True
CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
break
# Not find Depex
if not IsFoundDepex:
CouldBeLoaded = self.CheckArchProtocol()
DepexString = ''
FileDepex = None
# Append New Ffs
if CouldBeLoaded:
IsInstalled = True
NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
NewFfs.Depex = DepexString
if FileDepex != None:
ScheduleList.insert.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
else:
ScheduleList[FfsID] = NewFfs
else:
self.UnDispatchedFfsDict[FfsID].Depex = DepexString
for FfsID in ScheduleList:
NewFfs = ScheduleList.pop(FfsID)
FfsName = 'UnKnown'
self.OrderedFfsDict[FfsID] = NewFfs
self.LoadProtocol(Db, FfsID)
SqlCommand = """select Value2 from Inf
where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
RecordSet = Db.TblReport.Exec(SqlCommand)
if RecordSet != []:
FfsName = RecordSet[0][0]
if IsInstalled:
self.DisPatchDxe(Db)
def DisPatchPei(self, Db):
IsInstalled = False
for FfsID in self.UnDispatchedFfsDict:
CouldBeLoaded = True
DepexString = ''
FileDepex = None
Ffs = self.UnDispatchedFfsDict[FfsID]
if Ffs.Type == 0x06 or Ffs.Type == 0x08:
# Get Depex
for Section in Ffs.Sections.values():
if Section.Type == 0x1B:
CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
break
if Section.Type == 0x01:
CompressSections = Section._SubImages[4]
for CompressSection in CompressSections.Sections:
if CompressSection.Type == 0x1B:
CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
break
if CompressSection.Type == 0x02:
NewSections = CompressSection._SubImages[4]
for NewSection in NewSections.Sections:
if NewSection.Type == 0x1B:
CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
break
# Append New Ffs
if CouldBeLoaded:
IsInstalled = True
NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
NewFfs.Depex = DepexString
self.OrderedFfsDict[FfsID] = NewFfs
self.LoadPpi(Db, FfsID)
else:
self.UnDispatchedFfsDict[FfsID].Depex = DepexString
if IsInstalled:
self.DisPatchPei(Db)
def __str__(self):
global gIndention
gIndention += 4
FvInfo = '\n' + ' ' * gIndention
FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
gIndention -= 4
return FvInfo + FfsInfo
def _Unpack(self):
Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
self.empty()
self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
# traverse the FFS
EndOfFv = Size
FfsStartAddress = self.HeaderSize
LastFfsObj = None
while FfsStartAddress < EndOfFv:
FfsObj = Ffs()
FfsObj.frombuffer(self, FfsStartAddress)
FfsId = repr(FfsObj)
if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
if LastFfsObj != None:
LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
else:
if FfsId in self.FfsDict:
EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
ExtraData="\t%s @ %s\n\t%s @ %s" \
% (FfsObj.Guid, FfsObj.Offset,
self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
self.FfsDict[FfsId] = FfsObj
if LastFfsObj != None:
LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
FfsStartAddress += len(FfsObj)
#
# align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
# The next FFS must be at the latest next 8-byte aligned address
#
FfsStartAddress = (FfsStartAddress + 7) & (~7)
LastFfsObj = FfsObj
def _GetAttributes(self):
return self.GetField(self._ATTR_, 0)[0]
def _GetSize(self):
return self.GetField(self._LENGTH_, 0)[0]
def _GetChecksum(self):
return self.GetField(self._CHECKSUM_, 0)[0]
def _GetHeaderLength(self):
return self.GetField(self._HLEN_, 0)[0]
def _GetFileSystemGuid(self):
return gGuidStringFormat % self.GetField(self._GUID_, 0)
Attributes = property(_GetAttributes)
Size = property(_GetSize)
Checksum = property(_GetChecksum)
HeaderSize = property(_GetHeaderLength)
FileSystemGuid = property(_GetFileSystemGuid)
## CompressedImage() class
#
# A class for Compressed Image
#
class CompressedImage(Image):
# UncompressedLength = 4-byte
# CompressionType = 1-byte
_HEADER_ = struct.Struct("1I 1B")
_HEADER_SIZE_ = _HEADER_.size
_ORIG_SIZE_ = struct.Struct("1I")
_CMPRS_TYPE_ = struct.Struct("4x 1B")
def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None):
Image.__init__(m)
if UncompressedLength != None:
m.UncompressedLength = UncompressedLength
if CompressionType != None:
m.CompressionType = CompressionType
if CompressedData != None:
m.Data = CompressedData
def __str__(m):
global gIndention
S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength)
for Sec in m.Sections:
S += '\n' + str(Sec)
return S
def _SetOriginalSize(m, Size):
m.SetField(m._ORIG_SIZE_, 0, Size)
def _GetOriginalSize(m):
return m.GetField(m._ORIG_SIZE_)[0]
def _SetCompressionType(m, Type):
m.SetField(m._CMPRS_TYPE_, 0, Type)
def _GetCompressionType(m):
return m.GetField(m._CMPRS_TYPE_)[0]
def _GetSections(m):
try:
import EfiCompressor
TmpData = EfiCompressor.FrameworkDecompress(
m[m._HEADER_SIZE_:],
len(m) - m._HEADER_SIZE_
)
DecData = array('B')
DecData.fromstring(TmpData)
except:
import EfiCompressor
TmpData = EfiCompressor.UefiDecompress(
m[m._HEADER_SIZE_:],
len(m) - m._HEADER_SIZE_
)
DecData = array('B')
DecData.fromstring(TmpData)
SectionList = []
Offset = 0
while Offset < len(DecData):
Sec = Section()
try:
Sec.frombuffer(DecData, Offset)
Offset += Sec.Size
# the section is aligned to 4-byte boundary
except:
break
SectionList.append(Sec)
return SectionList
UncompressedLength = property(_GetOriginalSize, _SetOriginalSize)
CompressionType = property(_GetCompressionType, _SetCompressionType)
Sections = property(_GetSections)
## GuidDefinedImage() class
#
# A class for GUID Defined Image
#
class GuidDefinedImage(Image):
_HEADER_ = struct.Struct("1I2H8B 1H 1H")
_HEADER_SIZE_ = _HEADER_.size
_GUID_ = struct.Struct("1I2H8B")
_DATA_OFFSET_ = struct.Struct("16x 1H")
_ATTR_ = struct.Struct("18x 1H")
CRC32_GUID = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083"
TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779'
LZMA_COMPRESS_GUID = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF'
def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None):
Image.__init__(m)
if SectionDefinitionGuid != None:
m.SectionDefinitionGuid = SectionDefinitionGuid
if DataOffset != None:
m.DataOffset = DataOffset
if Attributes != None:
m.Attributes = Attributes
if Data != None:
m.Data = Data
def __str__(m):
S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid)
for Sec in m.Sections:
S += "\n" + str(Sec)
return S
def _Unpack(m):
# keep header in this Image object
m.empty()
m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
return len(m)
def _SetAttribute(m, Attribute):
m.SetField(m._ATTR_, 0, Attribute)
def _GetAttribute(m):
return m.GetField(m._ATTR_)[0]
def _SetGuid(m, Guid):
m.SetField(m._GUID_, 0, Guid)
def _GetGuid(m):
return m.GetField(m._GUID_)
def _SetDataOffset(m, Offset):
m.SetField(m._DATA_OFFSET_, 0, Offset)
def _GetDataOffset(m):
return m.GetField(m._DATA_OFFSET_)[0]
def _GetSections(m):
SectionList = []
Guid = gGuidStringFormat % m.SectionDefinitionGuid
if Guid == m.CRC32_GUID:
# skip the CRC32 value, we don't do CRC32 verification here
Offset = m.DataOffset - 4
while Offset < len(m):
Sec = Section()
try:
Sec.frombuffer(m, Offset)
Offset += Sec.Size
# the section is aligned to 4-byte boundary
Offset = (Offset + 3) & (~3)
except:
break
SectionList.append(Sec)
elif Guid == m.TIANO_COMPRESS_GUID:
try:
import EfiCompressor
# skip the header
Offset = m.DataOffset - 4
TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset)
DecData = array('B')
DecData.fromstring(TmpData)
Offset = 0
while Offset < len(DecData):
Sec = Section()
try:
Sec.frombuffer(DecData, Offset)
Offset += Sec.Size
# the section is aligned to 4-byte boundary
Offset = (Offset + 3) & (~3)
except:
break
SectionList.append(Sec)
except:
pass
elif Guid == m.LZMA_COMPRESS_GUID:
try:
import LzmaCompressor
# skip the header
Offset = m.DataOffset - 4
TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset)
DecData = array('B')
DecData.fromstring(TmpData)
Offset = 0
while Offset < len(DecData):
Sec = Section()
try:
Sec.frombuffer(DecData, Offset)
Offset += Sec.Size
# the section is aligned to 4-byte boundary
Offset = (Offset + 3) & (~3)
except:
break
SectionList.append(Sec)
except:
pass
return SectionList
Attributes = property(_GetAttribute, _SetAttribute)
SectionDefinitionGuid = property(_GetGuid, _SetGuid)
DataOffset = property(_GetDataOffset, _SetDataOffset)
Sections = property(_GetSections)
## Depex() class
#
# A class for Depex
#
class Depex(Image):
_HEADER_ = struct.Struct("")
_HEADER_SIZE_ = 0
_GUID_ = struct.Struct("1I2H8B")
_OPCODE_ = struct.Struct("1B")
_OPCODE_STRING_ = {
0x00 : "BEFORE",
0x01 : "AFTER",
0x02 : "PUSH",
0x03 : "AND",
0x04 : "OR",
0x05 : "NOT",
0x06 : "TRUE",
0x07 : "FALSE",
0x08 : "END",
0x09 : "SOR"
}
_NEXT_ = {
-1 : _OPCODE_, # first one in depex must be an opcdoe
0x00 : _GUID_, #"BEFORE",
0x01 : _GUID_, #"AFTER",
0x02 : _GUID_, #"PUSH",
0x03 : _OPCODE_, #"AND",
0x04 : _OPCODE_, #"OR",
0x05 : _OPCODE_, #"NOT",
0x06 : _OPCODE_, #"TRUE",
0x07 : _OPCODE_, #"FALSE",
0x08 : None, #"END",
0x09 : _OPCODE_, #"SOR"
}
def __init__(m):
Image.__init__(m)
m._ExprList = []
def __str__(m):
global gIndention
gIndention += 4
Indention = ' ' * gIndention
S = '\n'
for T in m.Expression:
if T in m._OPCODE_STRING_:
S += Indention + m._OPCODE_STRING_[T]
if T not in [0x00, 0x01, 0x02]:
S += '\n'
else:
S += ' ' + gGuidStringFormat % T + '\n'
gIndention -= 4
return S
def _Unpack(m):
# keep header in this Image object
m.empty()
m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
return len(m)
def _GetExpression(m):
if m._ExprList == []:
Offset = 0
CurrentData = m._OPCODE_
while Offset < len(m):
Token = CurrentData.unpack_from(m, Offset)
Offset += CurrentData.size
if len(Token) == 1:
Token = Token[0]
if Token in m._NEXT_:
CurrentData = m._NEXT_[Token]
else:
CurrentData = m._GUID_
else:
CurrentData = m._OPCODE_
m._ExprList.append(Token)
if CurrentData == None:
break
return m._ExprList
Expression = property(_GetExpression)
## Ui() class
#
# A class for Ui
#
class Ui(Image):
_HEADER_ = struct.Struct("")
_HEADER_SIZE_ = 0
def __init__(m):
Image.__init__(m)
def __str__(m):
return m.String
def _Unpack(m):
# keep header in this Image object
m.empty()
m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
return len(m)
def _GetUiString(m):
return codecs.utf_16_decode(m[0:-2].tostring())[0]
String = property(_GetUiString)
## Section() class
#
# A class for Section
#
class Section(Image):
_TypeName = {
0x00 : "<unknown>",
0x01 : "COMPRESSION",
0x02 : "GUID_DEFINED",
0x10 : "PE32",
0x11 : "PIC",
0x12 : "TE",
0x13 : "DXE_DEPEX",
0x14 : "VERSION",
0x15 : "USER_INTERFACE",
0x16 : "COMPATIBILITY16",
0x17 : "FIRMWARE_VOLUME_IMAGE",
0x18 : "FREEFORM_SUBTYPE_GUID",
0x19 : "RAW",
0x1B : "PEI_DEPEX"
}
_SectionSubImages = {
0x01 : CompressedImage,
0x02 : GuidDefinedImage,
0x17 : FirmwareVolume,
0x13 : Depex,
0x1B : Depex,
0x15 : Ui
}
# Size = 3-byte
# Type = 1-byte
_HEADER_ = struct.Struct("3B 1B")
_HEADER_SIZE_ = _HEADER_.size
# SubTypeGuid
# _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
_SIZE_ = struct.Struct("3B")
_TYPE_ = struct.Struct("3x 1B")
def __init__(m, Type=None, Size=None):
Image.__init__(m)
m._Alignment = 1
if Type != None:
m.Type = Type
if Size != None:
m.Size = Size
def __str__(m):
global gIndention
gIndention += 4
SectionInfo = ' ' * gIndention
if m.Type in m._TypeName:
SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size)
else:
SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size)
for Offset in m._SubImages:
SectionInfo += ", " + str(m._SubImages[Offset])
gIndention -= 4
return SectionInfo
def _Unpack(m):
m.empty()
Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_)
Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_)
Size = Size1 + (Size2 << 8) + (Size3 << 16)
if Type not in m._SectionSubImages:
# no need to extract sub-image, keep all in this Image object
m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size])
else:
# keep header in this Image object
m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_])
#
# use new Image object to represent payload, which may be another kind
# of image such as PE32
#
PayloadOffset = m._HEADER_SIZE_
PayloadLen = m.Size - m._HEADER_SIZE_
Payload = m._SectionSubImages[m.Type]()
Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen)
m._SubImages[PayloadOffset] = Payload
return Size
def _SetSize(m, Size):
Size1 = Size & 0xFF
Size2 = (Size & 0xFF00) >> 8
Size3 = (Size & 0xFF0000) >> 16
m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
def _GetSize(m):
Size1, Size2, Size3 = m.GetField(m._SIZE_)
return Size1 + (Size2 << 8) + (Size3 << 16)
def _SetType(m, Type):
m.SetField(m._TYPE_, 0, Type)
def _GetType(m):
return m.GetField(m._TYPE_)[0]
def _GetAlignment(m):
return m._Alignment
def _SetAlignment(m, Alignment):
m._Alignment = Alignment
AlignmentMask = Alignment - 1
# section alignment is actually for payload, so we need to add header size
PayloadOffset = m._OFF_ + m._HEADER_SIZE_
if (PayloadOffset & (~AlignmentMask)) == 0:
return
NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask)
while (NewOffset - PayloadOffset) < m._HEADER_SIZE_:
NewOffset += m._Alignment
def tofile(m, f):
m.Size = len(m)
Image.tofile(m, f)
for Offset in m._SubImages:
m._SubImages[Offset].tofile(f)
Type = property(_GetType, _SetType)
Size = property(_GetSize, _SetSize)
Alignment = property(_GetAlignment, _SetAlignment)
# SubTypeGuid = property(_GetGuid, _SetGuid)
## PadSection() class
#
# A class for Pad Section
#
class PadSection(Section):
def __init__(m, Size):
Section.__init__(m)
m.Type = 0x19
m.Size = Size
m.Data = [0] * (Size - m._HEADER_SIZE_)
## Ffs() class
#
# A class for Ffs Section
#
class Ffs(Image):
_FfsFormat = "24B%(payload_size)sB"
# skip IntegrityCheck
_HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B")
_HEADER_SIZE_ = _HEADER_.size
_NAME_ = struct.Struct("1I2H8B")
_INT_CHECK_ = struct.Struct("16x 1H")
_TYPE_ = struct.Struct("18x 1B")
_ATTR_ = struct.Struct("19x 1B")
_SIZE_ = struct.Struct("20x 3B")
_STATE_ = struct.Struct("23x 1B")
VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09"
FFS_ATTRIB_FIXED = 0x04
FFS_ATTRIB_DATA_ALIGNMENT = 0x38
FFS_ATTRIB_CHECKSUM = 0x40
_TypeName = {
0x00 : "<unknown>",
0x01 : "RAW",
0x02 : "FREEFORM",
0x03 : "SECURITY_CORE",
0x04 : "PEI_CORE",
0x05 : "DXE_CORE",
0x06 : "PEIM",
0x07 : "DRIVER",
0x08 : "COMBINED_PEIM_DRIVER",
0x09 : "APPLICATION",
0x0A : "SMM",
0x0B : "FIRMWARE_VOLUME_IMAGE",
0x0C : "COMBINED_SMM_DXE",
0x0D : "SMM_CORE",
0xc0 : "OEM_MIN",
0xdf : "OEM_MAX",
0xe0 : "DEBUG_MIN",
0xef : "DEBUG_MAX",
0xf0 : "FFS_MIN",
0xff : "FFS_MAX",
0xf0 : "FFS_PAD",
}
def __init__(self):
Image.__init__(self)
self.FreeSpace = 0
self.Sections = sdict()
self.Depex = ''
self.__ID__ = None
def __str__(self):
global gIndention
gIndention += 4
Indention = ' ' * gIndention
FfsInfo = Indention
FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
(Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)
SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections])
gIndention -= 4
return FfsInfo + SectionInfo + "\n"
def __len__(self):
return self.Size
def __repr__(self):
return self.__ID__
def _Unpack(self):
Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)
Size = Size1 + (Size2 << 8) + (Size3 << 16)
self.empty()
self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])
# Pad FFS may use the same GUID. We need to avoid it.
if self.Type == 0xf0:
self.__ID__ = str(uuid.uuid1()).upper()
else:
self.__ID__ = self.Guid
# Traverse the SECTION. RAW and PAD do not have sections
if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:
EndOfFfs = Size
SectionStartAddress = self._HEADER_SIZE_
while SectionStartAddress < EndOfFfs:
SectionObj = Section()
SectionObj.frombuffer(self, SectionStartAddress)
#f = open(repr(SectionObj), 'wb')
#SectionObj.Size = 0
#SectionObj.tofile(f)
#f.close()
self.Sections[SectionStartAddress] = SectionObj
SectionStartAddress += len(SectionObj)
SectionStartAddress = (SectionStartAddress + 3) & (~3)
def Pack(self):
pass
def SetFreeSpace(self, Size):
self.FreeSpace = Size
def _GetGuid(self):
return gGuidStringFormat % self.Name
def _SetName(self, Value):
# Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
self.SetField(self._NAME_, 0, Value)
def _GetName(self):
# Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
return self.GetField(self._NAME_)
def _SetSize(m, Size):
Size1 = Size & 0xFF
Size2 = (Size & 0xFF00) >> 8
Size3 = (Size & 0xFF0000) >> 16
m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
def _GetSize(m):
Size1, Size2, Size3 = m.GetField(m._SIZE_)
return Size1 + (Size2 << 8) + (Size3 << 16)
def _SetType(m, Type):
m.SetField(m._TYPE_, 0, Type)
def _GetType(m):
return m.GetField(m._TYPE_)[0]
def _SetAttributes(self, Value):
self.SetField(m._ATTR_, 0, Value)
def _GetAttributes(self):
return self.GetField(self._ATTR_)[0]
def _GetFixed(self):
if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:
return True
return False
def _GetCheckSum(self):
if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:
return True
return False
def _GetAlignment(self):
return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3
def _SetState(self, Value):
self.SetField(m._STATE_, 0, Value)
def _GetState(self):
return self.GetField(m._STATE_)[0]
Name = property(_GetName, _SetName)
Guid = property(_GetGuid)
Type = property(_GetType, _SetType)
Size = property(_GetSize, _SetSize)
Attributes = property(_GetAttributes, _SetAttributes)
Fixed = property(_GetFixed)
Checksum = property(_GetCheckSum)
Alignment = property(_GetAlignment)
State = property(_GetState, _SetState)
## PeImage() class
#
# A class for PE Image
#
class PeImage:
#
# just extract e_lfanew
#
_DosHeaderFormat = "60x 1I"
#
# Machine
# NumberOfSections
# SizeOfOptionalHeader
#
_FileHeaderFormat = "4x 1H 1H 4x 4x 4x 1H 2x"
#
# Magic
# SizeOfImage
# SizeOfHeaders
# CheckSum
# NumberOfRvaAndSizes
#
_OptionalHeader32Format = "1H 54x 1I 1I 1I 24x 1I"
_OptionalHeader64Format = ""
def __init__(self, Buf, Offset, Size):
self.Offset = Offset
self.Size = Size
self.Machine = 0x014c # IA32
self.NumberOfSections = 0
self.SizeOfImage = 0
self.SizeOfOptionalHeader = 0
self.Checksum = 0
self._PeImageBuf = Buf
self._SectionList = []
self._DosHeader = struct.Struct(PeImage._DosHeaderFormat)
self._FileHeader = struct.Struct(PeImage._FileHeaderFormat)
self._OptionalHeader32 = struct.Struct(PeImage._OptionalHeader32Format)
self.Buffer = None
self._Unpack()
def __str__(self):
pass
def __len__(self):
return self.Size
def _Unpack(self):
# from DOS header, get the offset of PE header
FileHeaderOffset, = self._DosHeader.unpack_from(self._PeImageBuf, self.Offset)
if FileHeaderOffset < struct.calcsize(self._DosHeaderFormat):
EdkLogger.error("PE+", 0, "Invalid offset of IMAGE_FILE_HEADER: %s" % FileHeaderOffset)
# from FILE header, get the optional header size
self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader = \
self._FileHeader.unpack_from(self._PeImageBuf, self.Offset + FileHeaderOffset)
print "Machine=%x NumberOfSections=%x SizeOfOptionalHeader=%x" % (self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader)
# optional header follows the FILE header
OptionalHeaderOffset = FileHeaderOffset + struct.calcsize(self._FileHeaderFormat)
Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes = \
self._OptionalHeader32.unpack_from(self._PeImageBuf, self.Offset + OptionalHeaderOffset)
print "Magic=%x SizeOfImage=%x SizeOfHeaders=%x, Checksum=%x, NumberOfRvaAndSizes=%x" % (Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes)
PeImageSectionTableOffset = OptionalHeaderOffset + self.SizeOfOptionalHeader
PeSections = PeSectionTable(self._PeImageBuf, self.Offset + PeImageSectionTableOffset, self.NumberOfSections)
print "%x" % PeSections.GetFileAddress(0x3920)
## PeSectionTable() class
#
# A class for PE Section Table
#
class PeSectionTable:
def __init__(self, Buf, Offset, NumberOfSections):
self._SectionList = []
SectionHeaderOffset = Offset
for TableIndex in range(0, NumberOfSections):
SectionHeader = PeSectionHeader(Buf, SectionHeaderOffset)
self._SectionList.append(SectionHeader)
SectionHeaderOffset += len(SectionHeader)
print SectionHeader
def GetFileAddress(self, Rva):
for PeSection in self._SectionList:
if Rva in PeSection:
return PeSection[Rva]
## PeSectionHeader() class
#
# A class for PE Section Header
#
class PeSectionHeader:
#
# VirtualAddress
# SizeOfRawData
# PointerToRawData
#
_HeaderFormat = "12x 1I 1I 1I 16x"
_HeaderLength = struct.calcsize(_HeaderFormat)
def __init__(self, Buf, Offset):
self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData = \
struct.unpack_from(self._HeaderFormat, Buf, Offset)
self.VirtualAddressEnd = self.VirtualAddressStart + self.SizeOfRawData - 1
def __str__(self):
return "VirtualAddress=%x, SizeOfRawData=%x, PointerToRawData=%x" % (self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData)
def __len__(self):
return self._HeaderLength
def __contains__(self, Rva):
return Rva >= self.VirtualAddressStart and Rva <= self.VirtualAddressEnd
def __getitem__(self, Rva):
return Rva - self.VirtualAddressStart + self.PointerToRawData
## LinkMap() class
#
# A class for Link Map
#
class LinkMap:
_StartFlag = {
"MSFT" : re.compile("Address +Publics by Value +Rva\+Base +Lib:Object"),
"GCC" : re.compile("^\.(text|bss|data|edata)"),
}
_MappingFormat = {
"MSFT" : re.compile("([0-9a-f]+):([0-9a-f]+)\s+_+([0-9A-Za-z]+)\s+([0-9a-f]+)\s+"),
"GCC" : re.compile("^(\.\w)?\s+(0x[0-9a-f]+)\s+_+([0-9A-Za-z]+)"),
}
def __init__(self, MapFile, MapType="MSFT"):
self.File = MapFile
self.MapType = MapType
self._Globals = {} # global:RVA
self._Parse()
def _Parse(self):
MapFile = open(self.File, 'r')
MappingTitle = self._StartFlag[self.MapType]
MappingFormat = self._MappingFormat[self.MapType]
MappingStart = False
try:
for Line in MapFile:
Line = Line.strip()
if not MappingStart:
if MappingTitle.match(Line) != None:
MappingStart = True
continue
ResultList = MappingFormat.findall(Line)
if len(ResultList) == 0 or len(ResultList[0]) != 4:
continue
self._Globals[ResultList[2]] = int(ResultList[3], 16)
EdkLogger.verbose(ResultList[0])
finally:
MapFile.close()
def __contains__(self, Var):
return Var in self._Globals
def __getitem__(self, Var):
if Var not in self._Globals:
return None
return self._Globals[Var]
## MultipleFv() class
#
# A class for Multiple FV
#
class MultipleFv(FirmwareVolume):
def __init__(self, FvList):
FirmwareVolume.__init__(self)
self.BasicInfo = []
for FvPath in FvList:
FvName = os.path.splitext(os.path.split(FvPath)[1])[0]
Fd = open(FvPath, 'rb')
Buf = array('B')
try:
Buf.fromfile(Fd, os.path.getsize(FvPath))
except EOFError:
pass
Fv = FirmwareVolume(FvName)
Fv.frombuffer(Buf, 0, len(Buf))
self.BasicInfo.append([Fv.Name, Fv.FileSystemGuid, Fv.Size])
self.FfsDict.append(Fv.FfsDict)
# Version and Copyright
__version_number__ = "0.01"
__version__ = "%prog Version " + __version_number__
__copyright__ = "Copyright (c) 2008, Intel Corporation. All rights reserved."
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
#
# @retval Options A optparse.Values object containing the parsed options
# @retval InputFile Path of file to be trimmed
#
def GetOptions():
OptionList = [
make_option("-a", "--arch", dest="Arch",
help="The input file is preprocessed source code, including C or assembly code"),
make_option("-p", "--platform", dest="ActivePlatform",
help="The input file is preprocessed VFR file"),
make_option("-m", "--module", dest="ActiveModule",
help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
make_option("-f", "--FDF-file", dest="FdfFile",
help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
make_option("-o", "--output", dest="OutputDirectory",
help="File to store the trimmed content"),
make_option("-t", "--toolchain-tag", dest="ToolChain",
help=""),
make_option("-k", "--msft", dest="MakefileType", action="store_const", const="nmake",
help=""),
make_option("-g", "--gcc", dest="MakefileType", action="store_const", const="gmake",
help=""),
make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,
help="Run verbosely"),
make_option("-d", "--debug", dest="LogLevel", type="int",
help="Run with debug information"),
make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET,
help="Run quietly"),
make_option("-?", action="help", help="show this help message and exit"),
]
# use clearer usage to override default usage message
UsageString = "%prog [-a ARCH] [-p PLATFORM] [-m MODULE] [-t TOOLCHAIN_TAG] [-k] [-g] [-v|-d <debug_level>|-q] [-o <output_directory>] [GenC|GenMake]"
Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)
Parser.set_defaults(Arch=[])
Parser.set_defaults(ActivePlatform=None)
Parser.set_defaults(ActiveModule=None)
Parser.set_defaults(OutputDirectory="build")
Parser.set_defaults(FdfFile=None)
Parser.set_defaults(ToolChain="MYTOOLS")
if sys.platform == "win32":
Parser.set_defaults(MakefileType="nmake")
else:
Parser.set_defaults(MakefileType="gmake")
Parser.set_defaults(LogLevel=EdkLogger.INFO)
Options, Args = Parser.parse_args()
# error check
if len(Args) == 0:
Options.Target = "genmake"
sys.argv.append("genmake")
elif len(Args) == 1:
Options.Target = Args[0].lower()
if Options.Target not in ["genc", "genmake"]:
EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Not supported target",
ExtraData="%s\n\n%s" % (Options.Target, Parser.get_usage()))
else:
EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Too many targets",
ExtraData=Parser.get_usage())
return Options
## Entrance method
#
# This method mainly dispatch specific methods per the command line options.
# If no error found, return zero value so the caller of this tool can know
# if it's executed successfully or not.
#
# @retval 0 Tool was successful
# @retval 1 Tool failed
#
def Main():
from build import build
try:
Option = GetOptions()
build.main()
except Exception, e:
print e
return 1
return 0
# This acts like the main() function for the script, unless it is 'import'ed into another script.
if __name__ == '__main__':
EdkLogger.Initialize()
# sys.exit(Main())
if len(sys.argv) > 1:
FilePath = sys.argv[1]
if FilePath.lower().endswith(".fv"):
fd = open(FilePath, 'rb')
buf = array('B')
try:
buf.fromfile(fd, os.path.getsize(FilePath))
except EOFError:
pass
fv = FirmwareVolume("FVRECOVERY")
fv.frombuffer(buf, 0, len(buf))
#fv.Dispatch(None)
print fv
elif FilePath.endswith(".efi"):
fd = open(FilePath, 'rb')
buf = array('B')
Size = os.path.getsize(FilePath)
try:
buf.fromfile(fd, Size)
except EOFError:
pass
PeSection = Section(Type=0x10)
PeSection.Data = buf
sf, ext = os.path.splitext(os.path.basename(FilePath))
sf += ".sec"
PeSection.tofile(open(sf, 'wb'))
elif FilePath.endswith(".map"):
mf = LinkMap(FilePath)