xref: /haiku/src/system/boot/platform/efi/arch/riscv64/relocation_func.cpp (revision 9ba143a5d09d1da4befaf5d4440bacb0c95a4e08)
104f1baa7SAlexander von Gluck IV // SPDX-License-Identifier: GPL-2.0+
204f1baa7SAlexander von Gluck IV /* reloc_riscv.c - position independent ELF shared object relocator
304f1baa7SAlexander von Gluck IV    Copyright (C) 2018 Alexander Graf <agraf@suse.de>
404f1baa7SAlexander von Gluck IV    Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
504f1baa7SAlexander von Gluck IV    Copyright (C) 1999 Hewlett-Packard Co.
604f1baa7SAlexander von Gluck IV 	Contributed by David Mosberger <davidm@hpl.hp.com>.
704f1baa7SAlexander von Gluck IV 
804f1baa7SAlexander von Gluck IV     All rights reserved.
904f1baa7SAlexander von Gluck IV 
1004f1baa7SAlexander von Gluck IV     Redistribution and use in source and binary forms, with or without
1104f1baa7SAlexander von Gluck IV     modification, are permitted provided that the following conditions
1204f1baa7SAlexander von Gluck IV     are met:
1304f1baa7SAlexander von Gluck IV 
1404f1baa7SAlexander von Gluck IV     * Redistributions of source code must retain the above copyright
1504f1baa7SAlexander von Gluck IV       notice, this list of conditions and the following disclaimer.
1604f1baa7SAlexander von Gluck IV     * Redistributions in binary form must reproduce the above
1704f1baa7SAlexander von Gluck IV       copyright notice, this list of conditions and the following
1804f1baa7SAlexander von Gluck IV       disclaimer in the documentation and/or other materials
1904f1baa7SAlexander von Gluck IV       provided with the distribution.
2004f1baa7SAlexander von Gluck IV     * Neither the name of Hewlett-Packard Co. nor the names of its
2104f1baa7SAlexander von Gluck IV       contributors may be used to endorse or promote products derived
2204f1baa7SAlexander von Gluck IV       from this software without specific prior written permission.
2304f1baa7SAlexander von Gluck IV 
2404f1baa7SAlexander von Gluck IV     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2504f1baa7SAlexander von Gluck IV     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2604f1baa7SAlexander von Gluck IV     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2704f1baa7SAlexander von Gluck IV     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2804f1baa7SAlexander von Gluck IV     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
2904f1baa7SAlexander von Gluck IV     BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
3004f1baa7SAlexander von Gluck IV     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3104f1baa7SAlexander von Gluck IV     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3204f1baa7SAlexander von Gluck IV     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3304f1baa7SAlexander von Gluck IV     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3404f1baa7SAlexander von Gluck IV     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3504f1baa7SAlexander von Gluck IV     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3604f1baa7SAlexander von Gluck IV     SUCH DAMAGE.
3704f1baa7SAlexander von Gluck IV */
3804f1baa7SAlexander von Gluck IV 
3904f1baa7SAlexander von Gluck IV #include <efi/types.h>
4004f1baa7SAlexander von Gluck IV #include <efi/system-table.h>
4104f1baa7SAlexander von Gluck IV 
4204f1baa7SAlexander von Gluck IV #include <elf.h>
4304f1baa7SAlexander von Gluck IV 
4404f1baa7SAlexander von Gluck IV #if __riscv_xlen == 64
4504f1baa7SAlexander von Gluck IV #define Elf_Dyn		Elf64_Dyn
4604f1baa7SAlexander von Gluck IV #define Elf_Rela	Elf64_Rela
4704f1baa7SAlexander von Gluck IV #define ELF_R_TYPE	ELF64_R_TYPE
4804f1baa7SAlexander von Gluck IV #else
4904f1baa7SAlexander von Gluck IV #define Elf_Dyn		Elf32_Dyn
5004f1baa7SAlexander von Gluck IV #define Elf_Rela	Elf32_Rela
5104f1baa7SAlexander von Gluck IV #define ELF_R_TYPE	ELF32_R_TYPE
5204f1baa7SAlexander von Gluck IV #endif
5304f1baa7SAlexander von Gluck IV 
5404f1baa7SAlexander von Gluck IV 
_relocate(long ldbase,Elf_Dyn * dyn,efi_handle image,efi_system_table * systab)55*9ba143a5SAlexander von Gluck IV extern "C" efi_status _relocate(long ldbase, Elf_Dyn *dyn,
5604f1baa7SAlexander von Gluck IV               efi_handle image __attribute__((__unused__)),
5704f1baa7SAlexander von Gluck IV               efi_system_table *systab __attribute__((__unused__)))
5804f1baa7SAlexander von Gluck IV {
5904f1baa7SAlexander von Gluck IV 	long relsz = 0, relent = 0;
6004f1baa7SAlexander von Gluck IV 	Elf_Rela *rel = 0;
6104f1baa7SAlexander von Gluck IV 	unsigned long *addr;
6204f1baa7SAlexander von Gluck IV 	int i;
6304f1baa7SAlexander von Gluck IV 
6404f1baa7SAlexander von Gluck IV 	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
6504f1baa7SAlexander von Gluck IV 		switch (dyn[i].d_tag) {
6604f1baa7SAlexander von Gluck IV 		case DT_RELA:
6704f1baa7SAlexander von Gluck IV 			rel = (Elf_Rela *)((ulong)dyn[i].d_un.d_ptr + ldbase);
6804f1baa7SAlexander von Gluck IV 			break;
6904f1baa7SAlexander von Gluck IV 		case DT_RELASZ:
7004f1baa7SAlexander von Gluck IV 			relsz = dyn[i].d_un.d_val;
7104f1baa7SAlexander von Gluck IV 			break;
7204f1baa7SAlexander von Gluck IV 		case DT_RELAENT:
7304f1baa7SAlexander von Gluck IV 			relent = dyn[i].d_un.d_val;
7404f1baa7SAlexander von Gluck IV 			break;
7504f1baa7SAlexander von Gluck IV 		default:
7604f1baa7SAlexander von Gluck IV 			break;
7704f1baa7SAlexander von Gluck IV 		}
7804f1baa7SAlexander von Gluck IV 	}
7904f1baa7SAlexander von Gluck IV 
8004f1baa7SAlexander von Gluck IV 	if (!rel && relent == 0)
8104f1baa7SAlexander von Gluck IV 		return EFI_SUCCESS;
8204f1baa7SAlexander von Gluck IV 
8304f1baa7SAlexander von Gluck IV 	if (!rel || relent == 0)
8404f1baa7SAlexander von Gluck IV 		return EFI_LOAD_ERROR;
8504f1baa7SAlexander von Gluck IV 
8604f1baa7SAlexander von Gluck IV 	while (relsz > 0) {
8704f1baa7SAlexander von Gluck IV 		/* apply the relocs */
8804f1baa7SAlexander von Gluck IV 		switch (ELF_R_TYPE(rel->r_info)) {
8904f1baa7SAlexander von Gluck IV 		case R_RISCV_RELATIVE:
9004f1baa7SAlexander von Gluck IV 			addr = (ulong *)(ldbase + rel->r_offset);
9104f1baa7SAlexander von Gluck IV 			*addr = ldbase + rel->r_addend;
9204f1baa7SAlexander von Gluck IV 			break;
9304f1baa7SAlexander von Gluck IV 		default:
9404f1baa7SAlexander von Gluck IV 			/* Panic */
9504f1baa7SAlexander von Gluck IV 			while (1) ;
9604f1baa7SAlexander von Gluck IV 		}
9704f1baa7SAlexander von Gluck IV 		rel = (Elf_Rela *)((char *)rel + relent);
9804f1baa7SAlexander von Gluck IV 		relsz -= relent;
9904f1baa7SAlexander von Gluck IV 	}
10004f1baa7SAlexander von Gluck IV 	return EFI_SUCCESS;
10104f1baa7SAlexander von Gluck IV }
102