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