reloc.c revision 293297
199651Sbenno/*- 299651Sbenno * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org> 399651Sbenno * All rights reserved. 499651Sbenno * 599651Sbenno * Redistribution and use in source and binary forms, with or without 699651Sbenno * modification, are permitted provided that the following conditions 799651Sbenno * are met: 899651Sbenno * 1. Redistributions of source code must retain the above copyright 999651Sbenno * notice, this list of conditions and the following disclaimer. 1099651Sbenno * 2. Redistributions in binary form must reproduce the above copyright 1199651Sbenno * notice, this list of conditions and the following disclaimer in the 1299651Sbenno * documentation and/or other materials provided with the distribution. 1399651Sbenno * 1499651Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1599651Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1699651Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1799651Sbenno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1899651Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1999651Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2099651Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2199651Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2299651Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2399651Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2499651Sbenno * SUCH DAMAGE. 2599651Sbenno */ 2699651Sbenno 2799651Sbenno#include <sys/cdefs.h> 2899651Sbenno__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/arch/amd64/reloc.c 293297 2016-01-07 02:22:45Z emaste $"); 2999651Sbenno 3099651Sbenno#include <sys/types.h> 3199651Sbenno#include <elf.h> 3299651Sbenno#include <efi.h> 3399651Sbenno#include <bootstrap.h> 3499651Sbenno 3599651Sbenno#ifdef __i386__ 3699651Sbenno#define ElfW_Rel Elf32_Rel 3799651Sbenno#define ElfW_Dyn Elf32_Dyn 3899651Sbenno#define ELFW_R_TYPE ELF32_R_TYPE 3999651Sbenno#elif __amd64__ 4099651Sbenno#define ElfW_Rel Elf64_Rel 4199651Sbenno#define ElfW_Dyn Elf64_Dyn 4299651Sbenno#define ELFW_R_TYPE ELF64_R_TYPE 4399651Sbenno#endif 4499651Sbenno 4599651Sbenno/* 4699651Sbenno * A simple relocator for IA32/AMD64 EFI binaries. 4799651Sbenno */ 4899651SbennoEFI_STATUS 4999651Sbenno_reloc(unsigned long ImageBase, ElfW_Dyn *dynamic, EFI_HANDLE image_handle, 5099651Sbenno EFI_SYSTEM_TABLE *system_table) 5199651Sbenno{ 5299651Sbenno unsigned long relsz, relent; 5399651Sbenno unsigned long *newaddr; 5499651Sbenno ElfW_Rel *rel; 5599651Sbenno ElfW_Dyn *dynp; 5699651Sbenno 5799651Sbenno /* 5899651Sbenno * Find the relocation address, its size and the relocation entry. 5999651Sbenno */ 6099651Sbenno relsz = 0; 6199651Sbenno relent = 0; 6299651Sbenno for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { 63218075Smarcel switch (dynp->d_tag) { 64218075Smarcel case DT_REL: 6599651Sbenno case DT_RELA: 6699651Sbenno rel = (ElfW_Rel *) ((unsigned long) dynp->d_un.d_ptr + 6799651Sbenno ImageBase); 6899651Sbenno break; 6999651Sbenno case DT_RELSZ: 70222813Sattilio case DT_RELASZ: 7199651Sbenno relsz = dynp->d_un.d_val; 72164987Smarcel break; 7399651Sbenno case DT_RELENT: 7499651Sbenno case DT_RELAENT: 7599651Sbenno relent = dynp->d_un.d_val; 7699651Sbenno break; 77209486Snwhitehorn default: 78171805Smarcel break; 7999651Sbenno } 80125708Sgrehan } 8199651Sbenno 8299651Sbenno /* 8399651Sbenno * Perform the actual relocation. 84171805Smarcel * XXX: We are reusing code for the amd64 version of this, but 85178628Smarcel * we must make sure the relocation types are the same. 8699651Sbenno */ 8799651Sbenno CTASSERT(R_386_NONE == R_X86_64_NONE); 88171805Smarcel CTASSERT(R_386_RELATIVE == R_X86_64_RELATIVE); 89171805Smarcel for (; relsz > 0; relsz -= relent) { 9099651Sbenno switch (ELFW_R_TYPE(rel->r_info)) { 9199651Sbenno case R_386_NONE: 92227293Sed /* No relocation needs be performed. */ 9399651Sbenno break; 94171805Smarcel case R_386_RELATIVE: 95164987Smarcel /* Address relative to the base address. */ 96164987Smarcel newaddr = (unsigned long *)(ImageBase + rel->r_offset); 97191450Smarcel *newaddr += ImageBase; 98191450Smarcel break; 99191450Smarcel default: 100191450Smarcel /* XXX: do we need other relocations ? */ 101212453Smav break; 102222813Sattilio } 103176918Smarcel rel = (ElfW_Rel *) ((caddr_t) rel + relent); 104176918Smarcel } 105265969Sian 106266676Snwhitehorn return (EFI_SUCCESS); 107164987Smarcel} 10899651Sbenno