^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OpenRISC module.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Linux architectural port borrowing liberally from similar works of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * others. All original copyrights apply as per the original source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * declaration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Modifications for the OpenRISC architecture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/moduleloader.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int apply_relocate_add(Elf32_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) const char *strtab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned int symindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) unsigned int relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct module *me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) Elf32_Sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) uint32_t *location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) uint32_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) pr_debug("Applying relocate section %u to %u\n", relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) sechdrs[relsec].sh_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* This is where to make the change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) + rel[i].r_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* This is the symbol it is referring to. Note that all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) undefined symbols have been resolved. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) + ELF32_R_SYM(rel[i].r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) value = sym->st_value + rel[i].r_addend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) switch (ELF32_R_TYPE(rel[i].r_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case R_OR32_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *location = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case R_OR32_CONST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *((uint16_t *)location + 1) = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case R_OR32_CONSTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *((uint16_t *)location + 1) = value >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case R_OR32_JUMPTARG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) value -= (uint32_t)location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) value >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) value &= 0x03ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) value |= *location & 0xfc000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *location = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) pr_err("module %s: Unknown relocation: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) me->name, ELF32_R_TYPE(rel[i].r_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }