1*3f234f5bSNigel Croxon /* reloc_mips64el.c - position independent MIPS64 ELF shared object relocator
2*3f234f5bSNigel Croxon Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
3*3f234f5bSNigel Croxon Copyright (C) 1999 Hewlett-Packard Co.
4*3f234f5bSNigel Croxon Contributed by David Mosberger <davidm@hpl.hp.com>.
5*3f234f5bSNigel Croxon Copyright (C) 2017 Lemote Co.
6*3f234f5bSNigel Croxon Contributed by Heiher <r@hev.cc>
7*3f234f5bSNigel Croxon
8*3f234f5bSNigel Croxon All rights reserved.
9*3f234f5bSNigel Croxon
10*3f234f5bSNigel Croxon Redistribution and use in source and binary forms, with or without
11*3f234f5bSNigel Croxon modification, are permitted provided that the following conditions
12*3f234f5bSNigel Croxon are met:
13*3f234f5bSNigel Croxon
14*3f234f5bSNigel Croxon * Redistributions of source code must retain the above copyright
15*3f234f5bSNigel Croxon notice, this list of conditions and the following disclaimer.
16*3f234f5bSNigel Croxon * Redistributions in binary form must reproduce the above
17*3f234f5bSNigel Croxon copyright notice, this list of conditions and the following
18*3f234f5bSNigel Croxon disclaimer in the documentation and/or other materials
19*3f234f5bSNigel Croxon provided with the distribution.
20*3f234f5bSNigel Croxon * Neither the name of Hewlett-Packard Co. nor the names of its
21*3f234f5bSNigel Croxon contributors may be used to endorse or promote products derived
22*3f234f5bSNigel Croxon from this software without specific prior written permission.
23*3f234f5bSNigel Croxon
24*3f234f5bSNigel Croxon THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25*3f234f5bSNigel Croxon CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26*3f234f5bSNigel Croxon INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27*3f234f5bSNigel Croxon MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28*3f234f5bSNigel Croxon DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
29*3f234f5bSNigel Croxon BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30*3f234f5bSNigel Croxon OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31*3f234f5bSNigel Croxon PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32*3f234f5bSNigel Croxon PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33*3f234f5bSNigel Croxon THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34*3f234f5bSNigel Croxon TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35*3f234f5bSNigel Croxon THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36*3f234f5bSNigel Croxon SUCH DAMAGE.
37*3f234f5bSNigel Croxon */
38*3f234f5bSNigel Croxon
39*3f234f5bSNigel Croxon #include <efi.h>
40*3f234f5bSNigel Croxon #include <efilib.h>
41*3f234f5bSNigel Croxon
42*3f234f5bSNigel Croxon #include <elf.h>
43*3f234f5bSNigel Croxon
_relocate(long ldbase,Elf64_Dyn * dyn,EFI_HANDLE image EFI_UNUSED,EFI_SYSTEM_TABLE * systab EFI_UNUSED)44*3f234f5bSNigel Croxon EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
45*3f234f5bSNigel Croxon EFI_HANDLE image EFI_UNUSED,
46*3f234f5bSNigel Croxon EFI_SYSTEM_TABLE *systab EFI_UNUSED)
47*3f234f5bSNigel Croxon {
48*3f234f5bSNigel Croxon long relsz = 0, relent = 0, gotsz = 0;
49*3f234f5bSNigel Croxon Elf64_Rel *rel = 0;
50*3f234f5bSNigel Croxon unsigned long *addr = 0;
51*3f234f5bSNigel Croxon int i;
52*3f234f5bSNigel Croxon
53*3f234f5bSNigel Croxon for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
54*3f234f5bSNigel Croxon switch (dyn[i].d_tag) {
55*3f234f5bSNigel Croxon case DT_REL:
56*3f234f5bSNigel Croxon rel = (Elf64_Rel*)
57*3f234f5bSNigel Croxon ((unsigned long)dyn[i].d_un.d_ptr
58*3f234f5bSNigel Croxon + ldbase);
59*3f234f5bSNigel Croxon break;
60*3f234f5bSNigel Croxon
61*3f234f5bSNigel Croxon case DT_RELSZ:
62*3f234f5bSNigel Croxon relsz = dyn[i].d_un.d_val;
63*3f234f5bSNigel Croxon break;
64*3f234f5bSNigel Croxon
65*3f234f5bSNigel Croxon case DT_RELENT:
66*3f234f5bSNigel Croxon relent = dyn[i].d_un.d_val;
67*3f234f5bSNigel Croxon break;
68*3f234f5bSNigel Croxon
69*3f234f5bSNigel Croxon case DT_PLTGOT:
70*3f234f5bSNigel Croxon addr = (unsigned long *)
71*3f234f5bSNigel Croxon ((unsigned long)dyn[i].d_un.d_ptr
72*3f234f5bSNigel Croxon + ldbase);
73*3f234f5bSNigel Croxon break;
74*3f234f5bSNigel Croxon
75*3f234f5bSNigel Croxon case DT_MIPS_LOCAL_GOTNO:
76*3f234f5bSNigel Croxon gotsz = dyn[i].d_un.d_val;
77*3f234f5bSNigel Croxon break;
78*3f234f5bSNigel Croxon
79*3f234f5bSNigel Croxon default:
80*3f234f5bSNigel Croxon break;
81*3f234f5bSNigel Croxon }
82*3f234f5bSNigel Croxon }
83*3f234f5bSNigel Croxon
84*3f234f5bSNigel Croxon if ((!rel && relent == 0) && (!addr && gotsz == 0))
85*3f234f5bSNigel Croxon return EFI_SUCCESS;
86*3f234f5bSNigel Croxon
87*3f234f5bSNigel Croxon if ((!rel && relent != 0) || (!addr && gotsz != 0))
88*3f234f5bSNigel Croxon return EFI_LOAD_ERROR;
89*3f234f5bSNigel Croxon
90*3f234f5bSNigel Croxon while (gotsz > 0) {
91*3f234f5bSNigel Croxon *addr += ldbase;
92*3f234f5bSNigel Croxon addr += 1;
93*3f234f5bSNigel Croxon gotsz --;
94*3f234f5bSNigel Croxon }
95*3f234f5bSNigel Croxon
96*3f234f5bSNigel Croxon while (relsz > 0) {
97*3f234f5bSNigel Croxon /* apply the relocs */
98*3f234f5bSNigel Croxon switch (ELF64_R_TYPE (swap_uint64 (rel->r_info))) {
99*3f234f5bSNigel Croxon case R_MIPS_NONE:
100*3f234f5bSNigel Croxon break;
101*3f234f5bSNigel Croxon
102*3f234f5bSNigel Croxon case (R_MIPS_64 << 8) | R_MIPS_REL32:
103*3f234f5bSNigel Croxon addr = (unsigned long *)
104*3f234f5bSNigel Croxon (ldbase + rel->r_offset);
105*3f234f5bSNigel Croxon *addr += ldbase;
106*3f234f5bSNigel Croxon break;
107*3f234f5bSNigel Croxon
108*3f234f5bSNigel Croxon default:
109*3f234f5bSNigel Croxon break;
110*3f234f5bSNigel Croxon }
111*3f234f5bSNigel Croxon rel = (Elf64_Rel*) ((char *) rel + relent);
112*3f234f5bSNigel Croxon relsz -= relent;
113*3f234f5bSNigel Croxon }
114*3f234f5bSNigel Croxon return EFI_SUCCESS;
115*3f234f5bSNigel Croxon }
116