commonlib/fsp_relocate: Add PE32+ support
Add support for PE32+ binaries which can be found on X64 UEFI builds. TEST: Able to relocate and boot a X64 FSP. Change-Id: I22586834d7c9f3ab3a5e31bba957584587ec14e0 Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/82680 Reviewed-by: Subrata Banik <subratabanik@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
f725c24c37
commit
f40f5b6dd5
@ -160,16 +160,17 @@ static FSP_INFO_HEADER *fsp_get_info_hdr(void *fsp, size_t fih_offset)
|
||||
|
||||
static int pe_relocate(uintptr_t new_addr, void *pe, void *fsp, size_t fih_off)
|
||||
{
|
||||
EFI_IMAGE_NT_HEADERS32 *peih;
|
||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *peih;
|
||||
EFI_IMAGE_DOS_HEADER *doshdr;
|
||||
EFI_IMAGE_OPTIONAL_HEADER32 *ophdr;
|
||||
EFI_IMAGE_OPTIONAL_HEADER64 *ophdr64;
|
||||
FSP_INFO_HEADER *fih;
|
||||
uint32_t roffset, rsize;
|
||||
uint32_t offset;
|
||||
uint8_t *pe_base = pe;
|
||||
uint32_t image_base;
|
||||
uint32_t img_base_off;
|
||||
uint32_t delta;
|
||||
uint64_t image_base;
|
||||
uint64_t img_base_off;
|
||||
uint64_t delta;
|
||||
|
||||
doshdr = pe;
|
||||
if (read_le16(&doshdr->e_magic) != EFI_IMAGE_DOS_SIGNATURE) {
|
||||
@ -179,15 +180,20 @@ static int pe_relocate(uintptr_t new_addr, void *pe, void *fsp, size_t fih_off)
|
||||
|
||||
peih = relative_offset(pe, doshdr->e_lfanew);
|
||||
|
||||
if (read_le32(&peih->Signature) != EFI_IMAGE_NT_SIGNATURE) {
|
||||
if (read_le32(&peih->Pe32.Signature) != EFI_IMAGE_NT_SIGNATURE) {
|
||||
printk(BIOS_ERR, "Invalid PE32 header\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ophdr = &peih->OptionalHeader;
|
||||
ophdr = &peih->Pe32.OptionalHeader;
|
||||
ophdr64 = &peih->Pe32Plus.OptionalHeader;
|
||||
|
||||
if (read_le16(&ophdr->Magic) != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
printk(BIOS_ERR, "No support for non-PE32 images\n");
|
||||
if (read_le16(&ophdr->Magic) == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
ophdr64 = NULL;
|
||||
} else if (read_le16(&ophdr64->Magic) == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
ophdr = NULL;
|
||||
} else {
|
||||
printk(BIOS_ERR, "No support for non-PE32/PE32+ images\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -197,21 +203,26 @@ static int pe_relocate(uintptr_t new_addr, void *pe, void *fsp, size_t fih_off)
|
||||
return -1;
|
||||
}
|
||||
image_base = read_le32(&fih->ImageBase);
|
||||
printk(FSP_DBG_LVL, "FSP InfoHdr Image Base is %x\n", image_base);
|
||||
printk(FSP_DBG_LVL, "FSP InfoHdr Image Base is %" PRIX64"\n", image_base);
|
||||
|
||||
delta = new_addr - image_base;
|
||||
|
||||
img_base_off = read_le32(&ophdr->ImageBase);
|
||||
printk(FSP_DBG_LVL, "lfanew 0x%x, delta-0x%x, FSP Base 0x%x, NT32ImageBase 0x%x, offset 0x%x\n",
|
||||
img_base_off = ophdr ? read_le32(&ophdr->ImageBase) : read_le64(&ophdr64->ImageBase);
|
||||
printk(FSP_DBG_LVL, "lfanew 0x%x, delta-0x%" PRIX64 ", FSP Base 0x%" PRIX64 ", NT32ImageBase 0x%" PRIX64 ", offset 0x%" PRIX64 "\n",
|
||||
read_le32(&doshdr->e_lfanew),
|
||||
delta, image_base, img_base_off,
|
||||
(uint32_t)((uint8_t *)&ophdr->ImageBase - pe_base));
|
||||
(uint64_t)((uint8_t *)(uintptr_t)img_base_off - pe_base));
|
||||
|
||||
printk(FSP_DBG_LVL, "relocating PE32%s image at addr - 0x%" PRIxPTR "\n", ophdr ? "" : "+", new_addr);
|
||||
if (ophdr) {
|
||||
rsize = read_le32(&ophdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
|
||||
roffset = read_le32(&ophdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
||||
} else {
|
||||
rsize = read_le32(&ophdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
|
||||
roffset = read_le32(&ophdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
||||
}
|
||||
|
||||
printk(FSP_DBG_LVL, "relocating PE32 image at addr - 0x%" PRIxPTR "\n", new_addr);
|
||||
rsize = read_le32(&ophdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
|
||||
roffset = read_le32(&ophdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
||||
printk(FSP_DBG_LVL, "relocation table at offset-%x,size=%x\n", roffset, rsize);
|
||||
// TODO - add support for PE32+ also
|
||||
|
||||
offset = roffset;
|
||||
while (offset < (roffset + rsize)) {
|
||||
@ -234,20 +245,23 @@ static int pe_relocate(uintptr_t new_addr, void *pe, void *fsp, size_t fih_off)
|
||||
uint16_t roff = reloc_offset(rdata[i]);
|
||||
uint16_t rtype = reloc_type(rdata[i]);
|
||||
uint32_t aoff = vaddr + roff;
|
||||
uint32_t val;
|
||||
printk(FSP_DBG_LVL, "\t\treloc type %x offset %x aoff %x, base-0x%x\n",
|
||||
uint64_t val;
|
||||
printk(FSP_DBG_LVL, "\t\treloc type %x offset %x aoff %x, base-0x%" PRIX64 "\n",
|
||||
rtype, roff, aoff, img_base_off);
|
||||
switch (rtype) {
|
||||
case EFI_IMAGE_REL_BASED_ABSOLUTE:
|
||||
continue;
|
||||
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||
val = read_le32(&pe_base[aoff]);
|
||||
printk(FSP_DBG_LVL, "Adjusting %p %x -> %x\n",
|
||||
printk(FSP_DBG_LVL, "Adjusting %p %" PRIX64 " -> %" PRIX64 "\n",
|
||||
&pe_base[aoff], val, val + delta);
|
||||
write_le32(&pe_base[aoff], val + delta);
|
||||
break;
|
||||
case EFI_IMAGE_REL_BASED_DIR64:
|
||||
printk(BIOS_ERR, "Unsupported DIR64\n");
|
||||
val = read_le64(&pe_base[aoff]);
|
||||
printk(FSP_DBG_LVL, "Adjusting %p %" PRIX64 " -> %" PRIX64 "\n",
|
||||
&pe_base[aoff], val, val + delta);
|
||||
write_le64(&pe_base[aoff], val + delta);
|
||||
break;
|
||||
default:
|
||||
printk(BIOS_ERR, "Unsupported relocation type %d\n",
|
||||
@ -257,10 +271,13 @@ static int pe_relocate(uintptr_t new_addr, void *pe, void *fsp, size_t fih_off)
|
||||
}
|
||||
offset += sizeof(*rdata) * rnum;
|
||||
}
|
||||
printk(FSP_DBG_LVL, "Adjust Image Base %x->%x\n",
|
||||
printk(FSP_DBG_LVL, "Adjust Image Base %" PRIX64 "->%" PRIX64 "\n",
|
||||
img_base_off, img_base_off + delta);
|
||||
img_base_off += delta;
|
||||
write_le32(&ophdr->ImageBase, img_base_off);
|
||||
if (ophdr)
|
||||
write_le32(&ophdr->ImageBase, img_base_off);
|
||||
else
|
||||
write_le64(&ophdr64->ImageBase, img_base_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user