xref: /DragonStub/gnuefi/reloc_mips64el.c (revision 3f234f5b6ff5c16c6ddd5f2c2513fb329aecd30a)
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