1*2dcd4e9eSSimon Glass /* 2*2dcd4e9eSSimon Glass * reloc_x86_64.c - position independent x86_64 ELF shared object relocator 3*2dcd4e9eSSimon Glass * Copyright (C) 1999 Hewlett-Packard Co. 4*2dcd4e9eSSimon Glass * Contributed by David Mosberger <davidm@hpl.hp.com>. 5*2dcd4e9eSSimon Glass * Copyright (C) 2005 Intel Co. 6*2dcd4e9eSSimon Glass * Contributed by Fenghua Yu <fenghua.yu@intel.com>. 7*2dcd4e9eSSimon Glass * 8*2dcd4e9eSSimon Glass * All rights reserved. 9*2dcd4e9eSSimon Glass * 10*2dcd4e9eSSimon Glass * SPDX-License-Identifier: BSD-3-Clause 11*2dcd4e9eSSimon Glass */ 12*2dcd4e9eSSimon Glass 13*2dcd4e9eSSimon Glass #include <common.h> 14*2dcd4e9eSSimon Glass #include <efi.h> 15*2dcd4e9eSSimon Glass #include <elf.h> 16*2dcd4e9eSSimon Glass #include <asm/elf.h> 17*2dcd4e9eSSimon Glass 18*2dcd4e9eSSimon Glass efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t image, 19*2dcd4e9eSSimon Glass struct efi_system_table *systab) 20*2dcd4e9eSSimon Glass { 21*2dcd4e9eSSimon Glass long relsz = 0, relent = 0; 22*2dcd4e9eSSimon Glass Elf64_Rel *rel = 0; 23*2dcd4e9eSSimon Glass unsigned long *addr; 24*2dcd4e9eSSimon Glass int i; 25*2dcd4e9eSSimon Glass 26*2dcd4e9eSSimon Glass for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { 27*2dcd4e9eSSimon Glass switch (dyn[i].d_tag) { 28*2dcd4e9eSSimon Glass case DT_RELA: 29*2dcd4e9eSSimon Glass rel = (Elf64_Rel *) 30*2dcd4e9eSSimon Glass ((unsigned long)dyn[i].d_un.d_ptr + ldbase); 31*2dcd4e9eSSimon Glass break; 32*2dcd4e9eSSimon Glass case DT_RELASZ: 33*2dcd4e9eSSimon Glass relsz = dyn[i].d_un.d_val; 34*2dcd4e9eSSimon Glass break; 35*2dcd4e9eSSimon Glass case DT_RELAENT: 36*2dcd4e9eSSimon Glass relent = dyn[i].d_un.d_val; 37*2dcd4e9eSSimon Glass break; 38*2dcd4e9eSSimon Glass default: 39*2dcd4e9eSSimon Glass break; 40*2dcd4e9eSSimon Glass } 41*2dcd4e9eSSimon Glass } 42*2dcd4e9eSSimon Glass 43*2dcd4e9eSSimon Glass if (!rel && relent == 0) 44*2dcd4e9eSSimon Glass return EFI_SUCCESS; 45*2dcd4e9eSSimon Glass 46*2dcd4e9eSSimon Glass if (!rel || relent == 0) 47*2dcd4e9eSSimon Glass return EFI_LOAD_ERROR; 48*2dcd4e9eSSimon Glass 49*2dcd4e9eSSimon Glass while (relsz > 0) { 50*2dcd4e9eSSimon Glass /* apply the relocs */ 51*2dcd4e9eSSimon Glass switch (ELF64_R_TYPE(rel->r_info)) { 52*2dcd4e9eSSimon Glass case R_X86_64_NONE: 53*2dcd4e9eSSimon Glass break; 54*2dcd4e9eSSimon Glass case R_X86_64_RELATIVE: 55*2dcd4e9eSSimon Glass addr = (unsigned long *)(ldbase + rel->r_offset); 56*2dcd4e9eSSimon Glass *addr += ldbase; 57*2dcd4e9eSSimon Glass break; 58*2dcd4e9eSSimon Glass default: 59*2dcd4e9eSSimon Glass break; 60*2dcd4e9eSSimon Glass } 61*2dcd4e9eSSimon Glass rel = (Elf64_Rel *)((char *)rel + relent); 62*2dcd4e9eSSimon Glass relsz -= relent; 63*2dcd4e9eSSimon Glass } 64*2dcd4e9eSSimon Glass 65*2dcd4e9eSSimon Glass return EFI_SUCCESS; 66*2dcd4e9eSSimon Glass } 67