0001
0002
0003
0004 #include <linux/moduleloader.h>
0005 #include <linux/elf.h>
0006 #include <linux/mm.h>
0007 #include <linux/vmalloc.h>
0008 #include <linux/slab.h>
0009 #include <linux/fs.h>
0010 #include <linux/string.h>
0011 #include <linux/kernel.h>
0012 #include <linux/spinlock.h>
0013
0014 #ifdef CONFIG_CPU_CK810
0015 #define IS_BSR32(hi16, lo16) (((hi16) & 0xFC00) == 0xE000)
0016 #define IS_JSRI32(hi16, lo16) ((hi16) == 0xEAE0)
0017
0018 #define CHANGE_JSRI_TO_LRW(addr) do { \
0019 *(uint16_t *)(addr) = (*(uint16_t *)(addr) & 0xFF9F) | 0x001a; \
0020 *((uint16_t *)(addr) + 1) = *((uint16_t *)(addr) + 1) & 0xFFFF; \
0021 } while (0)
0022
0023 #define SET_JSR32_R26(addr) do { \
0024 *(uint16_t *)(addr) = 0xE8Fa; \
0025 *((uint16_t *)(addr) + 1) = 0x0000; \
0026 } while (0)
0027
0028 static void jsri_2_lrw_jsr(uint32_t *location)
0029 {
0030 uint16_t *location_tmp = (uint16_t *)location;
0031
0032 if (IS_BSR32(*location_tmp, *(location_tmp + 1)))
0033 return;
0034
0035 if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) {
0036
0037 CHANGE_JSRI_TO_LRW(location);
0038
0039 SET_JSR32_R26(location + 1);
0040 }
0041 }
0042 #else
0043 static void inline jsri_2_lrw_jsr(uint32_t *location)
0044 {
0045 return;
0046 }
0047 #endif
0048
0049 int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
0050 unsigned int symindex, unsigned int relsec, struct module *me)
0051 {
0052 unsigned int i;
0053 Elf32_Rela *rel = (void *) sechdrs[relsec].sh_addr;
0054 Elf32_Sym *sym;
0055 uint32_t *location;
0056 short *temp;
0057
0058 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
0059
0060 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
0061 + rel[i].r_offset;
0062 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
0063 + ELF32_R_SYM(rel[i].r_info);
0064
0065 switch (ELF32_R_TYPE(rel[i].r_info)) {
0066 case R_CSKY_32:
0067
0068 *location = rel[i].r_addend + sym->st_value;
0069 break;
0070 case R_CSKY_PC32:
0071
0072 *location = rel[i].r_addend + sym->st_value
0073 - (uint32_t)location;
0074 break;
0075 case R_CSKY_PCRELJSR_IMM11BY2:
0076 break;
0077 case R_CSKY_PCRELJSR_IMM26BY2:
0078 jsri_2_lrw_jsr(location);
0079 break;
0080 case R_CSKY_ADDR_HI16:
0081 temp = ((short *)location) + 1;
0082 *temp = (short)
0083 ((rel[i].r_addend + sym->st_value) >> 16);
0084 break;
0085 case R_CSKY_ADDR_LO16:
0086 temp = ((short *)location) + 1;
0087 *temp = (short)
0088 ((rel[i].r_addend + sym->st_value) & 0xffff);
0089 break;
0090 default:
0091 pr_err("module %s: Unknown relocation: %u\n",
0092 me->name, ELF32_R_TYPE(rel[i].r_info));
0093 return -ENOEXEC;
0094 }
0095 }
0096 return 0;
0097 }