1530d68baSNigel Croxon /* reloc_aarch64.c - position independent x86 ELF shared object relocator
2530d68baSNigel Croxon Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
3530d68baSNigel Croxon Copyright (C) 1999 Hewlett-Packard Co.
4530d68baSNigel Croxon Contributed by David Mosberger <davidm@hpl.hp.com>.
5530d68baSNigel Croxon
6530d68baSNigel Croxon All rights reserved.
7530d68baSNigel Croxon
8530d68baSNigel Croxon Redistribution and use in source and binary forms, with or without
9530d68baSNigel Croxon modification, are permitted provided that the following conditions
10530d68baSNigel Croxon are met:
11530d68baSNigel Croxon
12530d68baSNigel Croxon * Redistributions of source code must retain the above copyright
13530d68baSNigel Croxon notice, this list of conditions and the following disclaimer.
14530d68baSNigel Croxon * Redistributions in binary form must reproduce the above
15530d68baSNigel Croxon copyright notice, this list of conditions and the following
16530d68baSNigel Croxon disclaimer in the documentation and/or other materials
17530d68baSNigel Croxon provided with the distribution.
18530d68baSNigel Croxon * Neither the name of Hewlett-Packard Co. nor the names of its
19530d68baSNigel Croxon contributors may be used to endorse or promote products derived
20530d68baSNigel Croxon from this software without specific prior written permission.
21530d68baSNigel Croxon
22530d68baSNigel Croxon THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23530d68baSNigel Croxon CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24530d68baSNigel Croxon INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25530d68baSNigel Croxon MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26530d68baSNigel Croxon DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
27530d68baSNigel Croxon BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
28530d68baSNigel Croxon OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29530d68baSNigel Croxon PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30530d68baSNigel Croxon PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31530d68baSNigel Croxon THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
32530d68baSNigel Croxon TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
33530d68baSNigel Croxon THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34530d68baSNigel Croxon SUCH DAMAGE.
35530d68baSNigel Croxon */
36530d68baSNigel Croxon
37530d68baSNigel Croxon #include <efi.h>
38530d68baSNigel Croxon #include <efilib.h>
39530d68baSNigel Croxon
40530d68baSNigel Croxon #include <elf.h>
41530d68baSNigel Croxon
_relocate(long ldbase,Elf64_Dyn * dyn,EFI_HANDLE image EFI_UNUSED,EFI_SYSTEM_TABLE * systab EFI_UNUSED)423dd05c7bSNigel Croxon EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
43*5ff74ecaSNigel Croxon EFI_HANDLE image EFI_UNUSED,
44*5ff74ecaSNigel Croxon EFI_SYSTEM_TABLE *systab EFI_UNUSED)
45530d68baSNigel Croxon {
46530d68baSNigel Croxon long relsz = 0, relent = 0;
47530d68baSNigel Croxon Elf64_Rela *rel = 0;
48530d68baSNigel Croxon unsigned long *addr;
49530d68baSNigel Croxon int i;
50530d68baSNigel Croxon
51530d68baSNigel Croxon for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
52530d68baSNigel Croxon switch (dyn[i].d_tag) {
53530d68baSNigel Croxon case DT_RELA:
54530d68baSNigel Croxon rel = (Elf64_Rela*)
55530d68baSNigel Croxon ((unsigned long)dyn[i].d_un.d_ptr
56530d68baSNigel Croxon + ldbase);
57530d68baSNigel Croxon break;
58530d68baSNigel Croxon
59530d68baSNigel Croxon case DT_RELASZ:
60530d68baSNigel Croxon relsz = dyn[i].d_un.d_val;
61530d68baSNigel Croxon break;
62530d68baSNigel Croxon
63530d68baSNigel Croxon case DT_RELAENT:
64530d68baSNigel Croxon relent = dyn[i].d_un.d_val;
65530d68baSNigel Croxon break;
66530d68baSNigel Croxon
67530d68baSNigel Croxon default:
68530d68baSNigel Croxon break;
69530d68baSNigel Croxon }
70530d68baSNigel Croxon }
71530d68baSNigel Croxon
72530d68baSNigel Croxon if (!rel && relent == 0)
73530d68baSNigel Croxon return EFI_SUCCESS;
74530d68baSNigel Croxon
75530d68baSNigel Croxon if (!rel || relent == 0)
76530d68baSNigel Croxon return EFI_LOAD_ERROR;
77530d68baSNigel Croxon
78530d68baSNigel Croxon while (relsz > 0) {
79530d68baSNigel Croxon /* apply the relocs */
80530d68baSNigel Croxon switch (ELF64_R_TYPE (rel->r_info)) {
81530d68baSNigel Croxon case R_AARCH64_NONE:
82530d68baSNigel Croxon break;
83530d68baSNigel Croxon
84530d68baSNigel Croxon case R_AARCH64_RELATIVE:
85530d68baSNigel Croxon addr = (unsigned long *)
86530d68baSNigel Croxon (ldbase + rel->r_offset);
87530d68baSNigel Croxon *addr = ldbase + rel->r_addend;
88530d68baSNigel Croxon break;
89530d68baSNigel Croxon
90530d68baSNigel Croxon default:
91530d68baSNigel Croxon break;
92530d68baSNigel Croxon }
93530d68baSNigel Croxon rel = (Elf64_Rela*) ((char *) rel + relent);
94530d68baSNigel Croxon relsz -= relent;
95530d68baSNigel Croxon }
96530d68baSNigel Croxon return EFI_SUCCESS;
97530d68baSNigel Croxon }
98