IntelFsp2Pkg/Tools: Add PE32 section rebasing support

The current SplitFspBin.py can only support TE image format
rebasing in an FSP binary. This patch adds PE32 image format
rebasing support.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Maurice Ma <maurice.ma@intel.com>
Reviewed-by: Satya Yarlagadda <Satya.p.yarlagadda@intel.com>
This commit is contained in:
Maurice Ma 2016-10-04 17:02:24 -07:00
parent 2cf9ecd226
commit e8a70885d8
1 changed files with 145 additions and 29 deletions

View File

@ -159,12 +159,102 @@ class EFI_TE_IMAGE_HEADER(Structure):
('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY) ('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY)
] ]
class EFI_IMAGE_DOS_HEADER(Structure):
_fields_ = [
('e_magic', c_uint16),
('e_cblp', c_uint16),
('e_cp', c_uint16),
('e_crlc', c_uint16),
('e_cparhdr', c_uint16),
('e_minalloc', c_uint16),
('e_maxalloc', c_uint16),
('e_ss', c_uint16),
('e_sp', c_uint16),
('e_csum', c_uint16),
('e_ip', c_uint16),
('e_cs', c_uint16),
('e_lfarlc', c_uint16),
('e_ovno', c_uint16),
('e_res', ARRAY(c_uint16, 4)),
('e_oemid', c_uint16),
('e_oeminfo', c_uint16),
('e_res2', ARRAY(c_uint16, 10)),
('e_lfanew', c_uint16)
]
class EFI_IMAGE_FILE_HEADER(Structure):
_fields_ = [
('Machine', c_uint16),
('NumberOfSections', c_uint16),
('TimeDateStamp', c_uint32),
('PointerToSymbolTable', c_uint32),
('NumberOfSymbols', c_uint32),
('SizeOfOptionalHeader', c_uint16),
('Characteristics', c_uint16)
]
class PE_RELOC_BLOCK_HEADER(Structure): class PE_RELOC_BLOCK_HEADER(Structure):
_fields_ = [ _fields_ = [
('PageRVA', c_uint32), ('PageRVA', c_uint32),
('BlockSize', c_uint32) ('BlockSize', c_uint32)
] ]
class EFI_IMAGE_OPTIONAL_HEADER32(Structure):
_fields_ = [
('Magic', c_uint16),
('MajorLinkerVersion', c_uint8),
('MinorLinkerVersion', c_uint8),
('SizeOfCode', c_uint32),
('SizeOfInitializedData', c_uint32),
('SizeOfUninitializedData', c_uint32),
('AddressOfEntryPoint', c_uint32),
('BaseOfCode', c_uint32),
('BaseOfData', c_uint32),
('ImageBase', c_uint32),
('SectionAlignment', c_uint32),
('FileAlignment', c_uint32),
('MajorOperatingSystemVersion', c_uint16),
('MinorOperatingSystemVersion', c_uint16),
('MajorImageVersion', c_uint16),
('MinorImageVersion', c_uint16),
('MajorSubsystemVersion', c_uint16),
('MinorSubsystemVersion', c_uint16),
('Win32VersionValue', c_uint32),
('SizeOfImage', c_uint32),
('SizeOfHeaders', c_uint32),
('CheckSum' , c_uint32),
('Subsystem', c_uint16),
('DllCharacteristics', c_uint16),
('SizeOfStackReserve', c_uint32),
('SizeOfStackCommit' , c_uint32),
('SizeOfHeapReserve', c_uint32),
('SizeOfHeapCommit' , c_uint32),
('LoaderFlags' , c_uint32),
('NumberOfRvaAndSizes', c_uint32),
('DataDirectory', ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
]
class EFI_IMAGE_NT_HEADERS32(Structure):
_fields_ = [
('Signature', c_uint32),
('FileHeader', EFI_IMAGE_FILE_HEADER),
('OptionalHeader', EFI_IMAGE_OPTIONAL_HEADER32)
]
class EFI_IMAGE_DIRECTORY_ENTRY:
EXPORT = 0
IMPORT = 1
RESOURCE = 2
EXCEPTION = 3
SECURITY = 4
BASERELOC = 5
DEBUG = 6
COPYRIGHT = 7
GLOBALPTR = 8
TLS = 9
LOAD_CONFIG = 10
class EFI_FV_FILETYPE: class EFI_FV_FILETYPE:
ALL = 0x00 ALL = 0x00
RAW = 0x01 RAW = 0x01
@ -431,26 +521,47 @@ class FirmwareDevice:
raise Exception("ERROR: Incorrect FV size in image !") raise Exception("ERROR: Incorrect FV size in image !")
self.CheckFsp () self.CheckFsp ()
class TeImage: class PeTeImage:
def __init__(self, offset, tedata): def __init__(self, offset, data):
self.Offset = offset self.Offset = offset
self.TeHdr = EFI_TE_IMAGE_HEADER.from_buffer (tedata, 0) tehdr = EFI_TE_IMAGE_HEADER.from_buffer (data, 0)
self.TeData = tedata if tehdr.Signature == 'VZ': # TE image
self.TeHdr = tehdr
elif tehdr.Signature == 'MZ': # PE32 image
self.TeHdr = None
self.DosHdr = EFI_IMAGE_DOS_HEADER.from_buffer (data, 0)
self.PeHdr = EFI_IMAGE_NT_HEADERS32.from_buffer (data, self.DosHdr.e_lfanew)
if self.PeHdr.Signature != 0x4550:
raise Exception("ERROR: Invalid PE32 header !")
if self.PeHdr.FileHeader.SizeOfOptionalHeader < EFI_IMAGE_OPTIONAL_HEADER32.DataDirectory.offset:
raise Exception("ERROR: Unsupported PE32 image !")
if self.PeHdr.OptionalHeader.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
raise Exception("ERROR: No relocation information available !")
self.Offset = offset
self.Data = data
self.RelocList = [] self.RelocList = []
def IsTeImage(self):
return self.TeHdr is not None
def ParseReloc(self): def ParseReloc(self):
rsize = self.TeHdr.DataDirectoryBaseReloc.Size if self.IsTeImage():
roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress rsize = self.TeHdr.DataDirectoryBaseReloc.Size
roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
else:
rsize = self.PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
roffset = self.PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
alignment = 4 alignment = 4
offset = roffset offset = roffset
while offset < roffset + rsize: while offset < roffset + rsize:
offset = AlignPtr(offset, 4) offset = AlignPtr(offset, 4)
blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.TeData, offset) blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.Data, offset)
offset += sizeof(blkhdr) offset += sizeof(blkhdr)
# Read relocation type,offset pairs # Read relocation type,offset pairs
rlen = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER) rlen = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)
rnum = rlen/sizeof(c_uint16) rnum = rlen/sizeof(c_uint16)
rdata = (c_uint16 * rnum).from_buffer(self.TeData, offset) rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)
for each in rdata: for each in rdata:
roff = each & 0xfff roff = each & 0xfff
rtype = each >> 12 rtype = each >> 12
@ -459,7 +570,9 @@ class TeImage:
if rtype != 3: # IMAGE_REL_BASED_HIGHLOW if rtype != 3: # IMAGE_REL_BASED_HIGHLOW
raise Exception("ERROR: Unsupported relocation type %d!" % rtype) raise Exception("ERROR: Unsupported relocation type %d!" % rtype)
# Calculate the offset of the relocation # Calculate the offset of the relocation
aoff = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + blkhdr.PageRVA + roff aoff = blkhdr.PageRVA + roff
if self.IsTeImage():
aoff += sizeof(self.TeHdr) - self.TeHdr.StrippedSize
self.RelocList.append((rtype, aoff)) self.RelocList.append((rtype, aoff))
offset += sizeof(rdata) offset += sizeof(rdata)
@ -478,10 +591,17 @@ class TeImage:
else: else:
raise Exception('ERROR: Unknown relocation type %d !' % rtype) raise Exception('ERROR: Unknown relocation type %d !' % rtype)
tehdr = self.TeHdr if self.IsTeImage():
tehdr.ImageBase += delta offset = self.Offset + EFI_TE_IMAGE_HEADER.ImageBase.offset
offset = self.Offset size = EFI_TE_IMAGE_HEADER.ImageBase.size
fdbin[offset:offset+sizeof(tehdr)] = bytearray(tehdr) else:
offset = self.Offset + self.DosHdr.e_lfanew
offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset
offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
size = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
value = Bytes2Val(fdbin[offset:offset+size]) + delta
fdbin[offset:offset+size] = Val2Bytes(value, size)
return count return count
@ -588,28 +708,24 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
delta = newbase - oldbase delta = newbase - oldbase
print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase) print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase)
telist = [] imglist = []
for fvidx in fsp.FvIdxList: for fvidx in fsp.FvIdxList:
fv = fd.FvList[fvidx] fv = fd.FvList[fvidx]
for ffs in fv.FfsList: for ffs in fv.FfsList:
for sec in ffs.SecList: for sec in ffs.SecList:
if sec.SecHdr.Type == EFI_SECTION_TYPE.TE: # TE if sec.SecHdr.Type in [EFI_SECTION_TYPE.TE, EFI_SECTION_TYPE.PE32]: # TE or PE32
offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr) offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
telist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr))) imglist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr)))
elif sec.SecHdr.Type == EFI_SECTION_TYPE.PE32: # PE
raise Exception("ERROR: PE32 Section is not supported !")
fcount = 0 fcount = 0
tecount = 0 pcount = 0
for (teoffset, telen) in telist: for (offset, length) in imglist:
tehdr = EFI_TE_IMAGE_HEADER.from_buffer (fd.FdData, teoffset) img = PeTeImage(offset, fd.FdData[offset:offset + length])
if 'VZ' != tehdr.Signature: img.ParseReloc()
raise Exception("ERROR: Invalid TE header !") pcount += img.Rebase(delta, newfspbin)
te = TeImage(teoffset, fd.FdData[teoffset:teoffset + telen]) fcount += 1
te.ParseReloc()
tecount += te.Rebase(delta, newfspbin) print " Patched %d entries in %d TE/PE32 images." % (pcount, fcount)
fcount += 1
print " Patched %d entries in %d TE images." % (tecount, fcount)
(count, applied) = fsp.Patch(delta, newfspbin) (count, applied) = fsp.Patch(delta, newfspbin)
print " Patched %d entries using FSP patch table." % applied print " Patched %d entries using FSP patch table." % applied