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