1*2dcd4e9eSSimon Glass /* 2*2dcd4e9eSSimon Glass * reloc_ia32.c - position independent x86 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 * 6*2dcd4e9eSSimon Glass * All rights reserved. 7*2dcd4e9eSSimon Glass * 8*2dcd4e9eSSimon Glass * SPDX-License-Identifier: BSD-3-Clause 9*2dcd4e9eSSimon Glass */ 10*2dcd4e9eSSimon Glass 11*2dcd4e9eSSimon Glass #include <common.h> 12*2dcd4e9eSSimon Glass #include <efi.h> 13*2dcd4e9eSSimon Glass #include <elf.h> 14*2dcd4e9eSSimon Glass #include <asm/elf.h> 15*2dcd4e9eSSimon Glass _relocate(long ldbase,Elf32_Dyn * dyn,efi_handle_t image,struct efi_system_table * systab)16*2dcd4e9eSSimon Glassefi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, 17*2dcd4e9eSSimon Glass struct efi_system_table *systab) 18*2dcd4e9eSSimon Glass { 19*2dcd4e9eSSimon Glass long relsz = 0, relent = 0; 20*2dcd4e9eSSimon Glass Elf32_Rel *rel = 0; 21*2dcd4e9eSSimon Glass unsigned long *addr; 22*2dcd4e9eSSimon Glass int i; 23*2dcd4e9eSSimon Glass 24*2dcd4e9eSSimon Glass for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { 25*2dcd4e9eSSimon Glass switch (dyn[i].d_tag) { 26*2dcd4e9eSSimon Glass case DT_REL: 27*2dcd4e9eSSimon Glass rel = (Elf32_Rel *)((unsigned long)dyn[i].d_un.d_ptr + 28*2dcd4e9eSSimon Glass ldbase); 29*2dcd4e9eSSimon Glass break; 30*2dcd4e9eSSimon Glass 31*2dcd4e9eSSimon Glass case DT_RELSZ: 32*2dcd4e9eSSimon Glass relsz = dyn[i].d_un.d_val; 33*2dcd4e9eSSimon Glass break; 34*2dcd4e9eSSimon Glass 35*2dcd4e9eSSimon Glass case DT_RELENT: 36*2dcd4e9eSSimon Glass relent = dyn[i].d_un.d_val; 37*2dcd4e9eSSimon Glass break; 38*2dcd4e9eSSimon Glass 39*2dcd4e9eSSimon Glass case DT_RELA: 40*2dcd4e9eSSimon Glass break; 41*2dcd4e9eSSimon Glass 42*2dcd4e9eSSimon Glass default: 43*2dcd4e9eSSimon Glass break; 44*2dcd4e9eSSimon Glass } 45*2dcd4e9eSSimon Glass } 46*2dcd4e9eSSimon Glass 47*2dcd4e9eSSimon Glass if (!rel && relent == 0) 48*2dcd4e9eSSimon Glass return EFI_SUCCESS; 49*2dcd4e9eSSimon Glass 50*2dcd4e9eSSimon Glass if (!rel || relent == 0) 51*2dcd4e9eSSimon Glass return EFI_LOAD_ERROR; 52*2dcd4e9eSSimon Glass 53*2dcd4e9eSSimon Glass while (relsz > 0) { 54*2dcd4e9eSSimon Glass /* apply the relocs */ 55*2dcd4e9eSSimon Glass switch (ELF32_R_TYPE(rel->r_info)) { 56*2dcd4e9eSSimon Glass case R_386_NONE: 57*2dcd4e9eSSimon Glass break; 58*2dcd4e9eSSimon Glass 59*2dcd4e9eSSimon Glass case R_386_RELATIVE: 60*2dcd4e9eSSimon Glass addr = (unsigned long *)(ldbase + rel->r_offset); 61*2dcd4e9eSSimon Glass *addr += ldbase; 62*2dcd4e9eSSimon Glass break; 63*2dcd4e9eSSimon Glass 64*2dcd4e9eSSimon Glass default: 65*2dcd4e9eSSimon Glass break; 66*2dcd4e9eSSimon Glass } 67*2dcd4e9eSSimon Glass rel = (Elf32_Rel *)((char *)rel + relent); 68*2dcd4e9eSSimon Glass relsz -= relent; 69*2dcd4e9eSSimon Glass } 70*2dcd4e9eSSimon Glass 71*2dcd4e9eSSimon Glass return EFI_SUCCESS; 72*2dcd4e9eSSimon Glass } 73