xref: /openbmc/u-boot/arch/x86/lib/reloc_x86_64_efi.c (revision 2dcd4e9e)
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