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