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