mirror of https://github.com/acidanthera/audk.git
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:
parent
2cf9ecd226
commit
e8a70885d8
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue