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