xref: /kvm-unit-tests/riscv/efi/reloc_riscv64.c (revision 6444ae208ce0085d0f5c5ffb15909ca3bbd49c84)
1da3404a5SAndrew Jones // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2da3404a5SAndrew Jones /* reloc_riscv.c - position independent ELF shared object relocator
3da3404a5SAndrew Jones    Copyright (C) 2018 Alexander Graf <agraf@suse.de>
4da3404a5SAndrew Jones    Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
5da3404a5SAndrew Jones    Copyright (C) 1999 Hewlett-Packard Co.
6da3404a5SAndrew Jones 	Contributed by David Mosberger <davidm@hpl.hp.com>.
7da3404a5SAndrew Jones 
8da3404a5SAndrew Jones     All rights reserved.
9da3404a5SAndrew Jones 
10da3404a5SAndrew Jones     Redistribution and use in source and binary forms, with or without
11da3404a5SAndrew Jones     modification, are permitted provided that the following conditions
12da3404a5SAndrew Jones     are met:
13da3404a5SAndrew Jones 
14da3404a5SAndrew Jones     * Redistributions of source code must retain the above copyright
15da3404a5SAndrew Jones       notice, this list of conditions and the following disclaimer.
16da3404a5SAndrew Jones     * Redistributions in binary form must reproduce the above
17da3404a5SAndrew Jones       copyright notice, this list of conditions and the following
18da3404a5SAndrew Jones       disclaimer in the documentation and/or other materials
19da3404a5SAndrew Jones       provided with the distribution.
20da3404a5SAndrew Jones     * Neither the name of Hewlett-Packard Co. nor the names of its
21da3404a5SAndrew Jones       contributors may be used to endorse or promote products derived
22da3404a5SAndrew Jones       from this software without specific prior written permission.
23da3404a5SAndrew Jones 
24da3404a5SAndrew Jones     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25da3404a5SAndrew Jones     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26da3404a5SAndrew Jones     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27da3404a5SAndrew Jones     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28da3404a5SAndrew Jones     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
29da3404a5SAndrew Jones     BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30da3404a5SAndrew Jones     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31da3404a5SAndrew Jones     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32da3404a5SAndrew Jones     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33da3404a5SAndrew Jones     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34da3404a5SAndrew Jones     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35da3404a5SAndrew Jones     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36da3404a5SAndrew Jones     SUCH DAMAGE.
37da3404a5SAndrew Jones */
38da3404a5SAndrew Jones 
39da3404a5SAndrew Jones #include <efi.h>
40da3404a5SAndrew Jones 
41da3404a5SAndrew Jones #include <elf.h>
42da3404a5SAndrew Jones 
43da3404a5SAndrew Jones #define Elf_Dyn		Elf64_Dyn
44da3404a5SAndrew Jones #define Elf_Rela	Elf64_Rela
45da3404a5SAndrew Jones #define ELF_R_TYPE	ELF64_R_TYPE
46da3404a5SAndrew Jones 
_relocate(long ldbase,Elf64_Dyn * dyn,efi_handle_t handle,efi_system_table_t * sys_tab)47*a403033cSAndrew Jones efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle,
48*a403033cSAndrew Jones 		       efi_system_table_t *sys_tab)
49da3404a5SAndrew Jones {
50da3404a5SAndrew Jones 	long relsz = 0, relent = 0;
51da3404a5SAndrew Jones 	Elf_Rela *rel = NULL;
52da3404a5SAndrew Jones 	unsigned long *addr;
53da3404a5SAndrew Jones 	int i;
54da3404a5SAndrew Jones 
55da3404a5SAndrew Jones 	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
56da3404a5SAndrew Jones 		switch (dyn[i].d_tag) {
57da3404a5SAndrew Jones 		case DT_RELA:
58da3404a5SAndrew Jones 			rel = (Elf_Rela *)((unsigned long)dyn[i].d_un.d_ptr + ldbase);
59da3404a5SAndrew Jones 			break;
60da3404a5SAndrew Jones 		case DT_RELASZ:
61da3404a5SAndrew Jones 			relsz = dyn[i].d_un.d_val;
62da3404a5SAndrew Jones 			break;
63da3404a5SAndrew Jones 		case DT_RELAENT:
64da3404a5SAndrew Jones 			relent = dyn[i].d_un.d_val;
65da3404a5SAndrew Jones 			break;
66da3404a5SAndrew Jones 		default:
67da3404a5SAndrew Jones 			break;
68da3404a5SAndrew Jones 		}
69da3404a5SAndrew Jones 	}
70da3404a5SAndrew Jones 
71da3404a5SAndrew Jones 	if (!rel && relent == 0)
72da3404a5SAndrew Jones 		return EFI_SUCCESS;
73da3404a5SAndrew Jones 
74da3404a5SAndrew Jones 	if (!rel || relent == 0)
75da3404a5SAndrew Jones 		return EFI_LOAD_ERROR;
76da3404a5SAndrew Jones 
77da3404a5SAndrew Jones 	while (relsz > 0) {
78da3404a5SAndrew Jones 		/* apply the relocs */
79da3404a5SAndrew Jones 		switch (ELF_R_TYPE(rel->r_info)) {
80da3404a5SAndrew Jones 		case R_RISCV_RELATIVE:
81da3404a5SAndrew Jones 			addr = (unsigned long *)(ldbase + rel->r_offset);
82da3404a5SAndrew Jones 			*addr = ldbase + rel->r_addend;
83da3404a5SAndrew Jones 			break;
84da3404a5SAndrew Jones 		default:
85da3404a5SAndrew Jones 				break;
86da3404a5SAndrew Jones 		}
87da3404a5SAndrew Jones 		rel = (Elf_Rela *)((char *)rel + relent);
88da3404a5SAndrew Jones 		relsz -= relent;
89da3404a5SAndrew Jones 	}
90da3404a5SAndrew Jones 	return EFI_SUCCESS;
91da3404a5SAndrew Jones }
92