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