xref: /openbmc/u-boot/arch/riscv/lib/reloc_riscv_efi.c (revision b71bb87af90f54ff109fa0449d07d91764c0794a)
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