xref: /haiku/src/system/boot/platform/efi/arch/arm64/relocation_func.cpp (revision 3b49957171c60b8c7b7d975f0f6fa3c1d4929652)
1811da1f1SAugustin Cavalier /* reloc_aarch64.c - position independent x86 ELF shared object relocator
2811da1f1SAugustin Cavalier    Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
3811da1f1SAugustin Cavalier    Copyright (C) 1999 Hewlett-Packard Co.
4811da1f1SAugustin Cavalier 	Contributed by David Mosberger <davidm@hpl.hp.com>.
5811da1f1SAugustin Cavalier 
6811da1f1SAugustin Cavalier     All rights reserved.
7811da1f1SAugustin Cavalier 
8811da1f1SAugustin Cavalier     Redistribution and use in source and binary forms, with or without
9811da1f1SAugustin Cavalier     modification, are permitted provided that the following conditions
10811da1f1SAugustin Cavalier     are met:
11811da1f1SAugustin Cavalier 
12811da1f1SAugustin Cavalier     * Redistributions of source code must retain the above copyright
13811da1f1SAugustin Cavalier       notice, this list of conditions and the following disclaimer.
14811da1f1SAugustin Cavalier     * Redistributions in binary form must reproduce the above
15811da1f1SAugustin Cavalier       copyright notice, this list of conditions and the following
16811da1f1SAugustin Cavalier       disclaimer in the documentation and/or other materials
17811da1f1SAugustin Cavalier       provided with the distribution.
18811da1f1SAugustin Cavalier     * Neither the name of Hewlett-Packard Co. nor the names of its
19811da1f1SAugustin Cavalier       contributors may be used to endorse or promote products derived
20811da1f1SAugustin Cavalier       from this software without specific prior written permission.
21811da1f1SAugustin Cavalier 
22811da1f1SAugustin Cavalier     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23811da1f1SAugustin Cavalier     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24811da1f1SAugustin Cavalier     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25811da1f1SAugustin Cavalier     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26811da1f1SAugustin Cavalier     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
27811da1f1SAugustin Cavalier     BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
28811da1f1SAugustin Cavalier     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29811da1f1SAugustin Cavalier     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30811da1f1SAugustin Cavalier     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31811da1f1SAugustin Cavalier     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
32811da1f1SAugustin Cavalier     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
33811da1f1SAugustin Cavalier     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34811da1f1SAugustin Cavalier     SUCH DAMAGE.
35811da1f1SAugustin Cavalier */
36811da1f1SAugustin Cavalier 
37817c6ca4SAlexander von Gluck IV #include <efi/types.h>
38817c6ca4SAlexander von Gluck IV #include <efi/system-table.h>
39811da1f1SAugustin Cavalier 
40811da1f1SAugustin Cavalier #include <elf.h>
41811da1f1SAugustin Cavalier 
_relocate(long ldbase,Elf64_Dyn * dyn,efi_handle image,efi_system_table * systab)42817c6ca4SAlexander von Gluck IV extern "C" efi_status _relocate (long ldbase, Elf64_Dyn *dyn,
43*3b499571SFredrik Holmqvist 		      efi_handle image __attribute__((__unused__)),
44*3b499571SFredrik Holmqvist 		      efi_system_table *systab __attribute__((__unused__)))
45811da1f1SAugustin Cavalier {
46811da1f1SAugustin Cavalier 	long relsz = 0, relent = 0;
47811da1f1SAugustin Cavalier 	Elf64_Rela *rel = 0;
48811da1f1SAugustin Cavalier 	unsigned long *addr;
49811da1f1SAugustin Cavalier 	int i;
50811da1f1SAugustin Cavalier 
51811da1f1SAugustin Cavalier 	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
52811da1f1SAugustin Cavalier 		switch (dyn[i].d_tag) {
53811da1f1SAugustin Cavalier 			case DT_RELA:
54811da1f1SAugustin Cavalier 				rel = (Elf64_Rela*)
55811da1f1SAugustin Cavalier 					((unsigned long)dyn[i].d_un.d_ptr
56811da1f1SAugustin Cavalier 					 + ldbase);
57811da1f1SAugustin Cavalier 				break;
58811da1f1SAugustin Cavalier 
59811da1f1SAugustin Cavalier 			case DT_RELASZ:
60811da1f1SAugustin Cavalier 				relsz = dyn[i].d_un.d_val;
61811da1f1SAugustin Cavalier 				break;
62811da1f1SAugustin Cavalier 
63811da1f1SAugustin Cavalier 			case DT_RELAENT:
64811da1f1SAugustin Cavalier 				relent = dyn[i].d_un.d_val;
65811da1f1SAugustin Cavalier 				break;
66811da1f1SAugustin Cavalier 
67811da1f1SAugustin Cavalier 			default:
68811da1f1SAugustin Cavalier 				break;
69811da1f1SAugustin Cavalier 		}
70811da1f1SAugustin Cavalier 	}
71811da1f1SAugustin Cavalier 
72811da1f1SAugustin Cavalier 	if (!rel && relent == 0)
73811da1f1SAugustin Cavalier 		return EFI_SUCCESS;
74811da1f1SAugustin Cavalier 
75811da1f1SAugustin Cavalier 	if (!rel || relent == 0)
76811da1f1SAugustin Cavalier 		return EFI_LOAD_ERROR;
77811da1f1SAugustin Cavalier 
78811da1f1SAugustin Cavalier 	while (relsz > 0) {
79811da1f1SAugustin Cavalier 		/* apply the relocs */
80811da1f1SAugustin Cavalier 		switch (ELF64_R_TYPE (rel->r_info)) {
81811da1f1SAugustin Cavalier 			case R_AARCH64_NONE:
82811da1f1SAugustin Cavalier 				break;
83811da1f1SAugustin Cavalier 
84811da1f1SAugustin Cavalier 			case R_AARCH64_RELATIVE:
85811da1f1SAugustin Cavalier 				addr = (unsigned long *)
86811da1f1SAugustin Cavalier 					(ldbase + rel->r_offset);
87811da1f1SAugustin Cavalier 				*addr = ldbase + rel->r_addend;
88811da1f1SAugustin Cavalier 				break;
89811da1f1SAugustin Cavalier 
90811da1f1SAugustin Cavalier 			default:
91811da1f1SAugustin Cavalier 				break;
92811da1f1SAugustin Cavalier 		}
93811da1f1SAugustin Cavalier 		rel = (Elf64_Rela*) ((char *) rel + relent);
94811da1f1SAugustin Cavalier 		relsz -= relent;
95811da1f1SAugustin Cavalier 	}
96811da1f1SAugustin Cavalier 	return EFI_SUCCESS;
97811da1f1SAugustin Cavalier }
98