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