17215787cSRick Chen // SPDX-License-Identifier: GPL-2.0+
2493d1e88SAlexander Graf /* reloc_riscv.c - position independent ELF shared object relocator
3493d1e88SAlexander Graf Copyright (C) 2018 Alexander Graf <agraf@suse.de>
4493d1e88SAlexander Graf Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
5493d1e88SAlexander Graf Copyright (C) 1999 Hewlett-Packard Co.
6493d1e88SAlexander Graf Contributed by David Mosberger <davidm@hpl.hp.com>.
7493d1e88SAlexander Graf
8493d1e88SAlexander Graf All rights reserved.
9493d1e88SAlexander Graf
10493d1e88SAlexander Graf Redistribution and use in source and binary forms, with or without
11493d1e88SAlexander Graf modification, are permitted provided that the following conditions
12493d1e88SAlexander Graf are met:
13493d1e88SAlexander Graf
14493d1e88SAlexander Graf * Redistributions of source code must retain the above copyright
15493d1e88SAlexander Graf notice, this list of conditions and the following disclaimer.
16493d1e88SAlexander Graf * Redistributions in binary form must reproduce the above
17493d1e88SAlexander Graf copyright notice, this list of conditions and the following
18493d1e88SAlexander Graf disclaimer in the documentation and/or other materials
19493d1e88SAlexander Graf provided with the distribution.
20493d1e88SAlexander Graf * Neither the name of Hewlett-Packard Co. nor the names of its
21493d1e88SAlexander Graf contributors may be used to endorse or promote products derived
22493d1e88SAlexander Graf from this software without specific prior written permission.
23493d1e88SAlexander Graf
24493d1e88SAlexander Graf THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25493d1e88SAlexander Graf CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26493d1e88SAlexander Graf INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27493d1e88SAlexander Graf MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28493d1e88SAlexander Graf DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
29493d1e88SAlexander Graf BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30493d1e88SAlexander Graf OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31493d1e88SAlexander Graf PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32493d1e88SAlexander Graf PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33493d1e88SAlexander Graf THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34493d1e88SAlexander Graf TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35493d1e88SAlexander Graf THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36493d1e88SAlexander Graf SUCH DAMAGE.
37493d1e88SAlexander Graf */
38493d1e88SAlexander Graf
39493d1e88SAlexander Graf #include <efi.h>
40493d1e88SAlexander Graf
41493d1e88SAlexander Graf #include <elf.h>
42493d1e88SAlexander Graf
43493d1e88SAlexander Graf #if __riscv_xlen == 64
44493d1e88SAlexander Graf #define Elf_Dyn Elf64_Dyn
45493d1e88SAlexander Graf #define Elf_Rela Elf64_Rela
46493d1e88SAlexander Graf #define ELF_R_TYPE ELF64_R_TYPE
47493d1e88SAlexander Graf #else
48493d1e88SAlexander Graf #define Elf_Dyn Elf32_Dyn
49493d1e88SAlexander Graf #define Elf_Rela Elf32_Rela
50493d1e88SAlexander Graf #define ELF_R_TYPE ELF32_R_TYPE
51493d1e88SAlexander Graf #endif
52493d1e88SAlexander Graf
_relocate(long ldbase,Elf_Dyn * dyn)53*b71bb87aSIvan Gorinov efi_status_t EFIAPI _relocate(long ldbase, Elf_Dyn *dyn)
54493d1e88SAlexander Graf {
55493d1e88SAlexander Graf long relsz = 0, relent = 0;
56493d1e88SAlexander Graf Elf_Rela *rel = 0;
57493d1e88SAlexander Graf unsigned long *addr;
58493d1e88SAlexander Graf int i;
59493d1e88SAlexander Graf
60493d1e88SAlexander Graf for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
61493d1e88SAlexander Graf switch (dyn[i].d_tag) {
62493d1e88SAlexander Graf case DT_RELA:
63493d1e88SAlexander Graf rel = (Elf_Rela *)((ulong)dyn[i].d_un.d_ptr + ldbase);
64493d1e88SAlexander Graf break;
65493d1e88SAlexander Graf case DT_RELASZ:
66493d1e88SAlexander Graf relsz = dyn[i].d_un.d_val;
67493d1e88SAlexander Graf break;
68493d1e88SAlexander Graf case DT_RELAENT:
69493d1e88SAlexander Graf relent = dyn[i].d_un.d_val;
70493d1e88SAlexander Graf break;
71493d1e88SAlexander Graf default:
72493d1e88SAlexander Graf break;
73493d1e88SAlexander Graf }
74493d1e88SAlexander Graf }
75493d1e88SAlexander Graf
76493d1e88SAlexander Graf if (!rel && relent == 0)
77493d1e88SAlexander Graf return EFI_SUCCESS;
78493d1e88SAlexander Graf
79493d1e88SAlexander Graf if (!rel || relent == 0)
80493d1e88SAlexander Graf return EFI_LOAD_ERROR;
81493d1e88SAlexander Graf
82493d1e88SAlexander Graf while (relsz > 0) {
83493d1e88SAlexander Graf /* apply the relocs */
84493d1e88SAlexander Graf switch (ELF_R_TYPE(rel->r_info)) {
85493d1e88SAlexander Graf case R_RISCV_RELATIVE:
86493d1e88SAlexander Graf addr = (ulong *)(ldbase + rel->r_offset);
87493d1e88SAlexander Graf *addr = ldbase + rel->r_addend;
88493d1e88SAlexander Graf break;
89493d1e88SAlexander Graf default:
90493d1e88SAlexander Graf /* Panic */
91493d1e88SAlexander Graf while (1) ;
92493d1e88SAlexander Graf }
93493d1e88SAlexander Graf rel = (Elf_Rela *)((char *)rel + relent);
94493d1e88SAlexander Graf relsz -= relent;
95493d1e88SAlexander Graf }
96493d1e88SAlexander Graf return EFI_SUCCESS;
97493d1e88SAlexander Graf }
98