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