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