1/* 2 * Copyright 2004-2009 Analog Devices Inc. 3 * 4 * Licensed under the GPL-2 or later 5 */ 6 7#define pr_fmt(fmt) "module %s: " fmt 8 9#include <linux/moduleloader.h> 10#include <linux/elf.h> 11#include <linux/vmalloc.h> 12#include <linux/fs.h> 13#include <linux/string.h> 14#include <linux/kernel.h> 15#include <asm/dma.h> 16#include <asm/cacheflush.h> 17#include <asm/uaccess.h> 18 19void *module_alloc(unsigned long size) 20{ 21 if (size == 0) 22 return NULL; 23 return vmalloc(size); 24} 25 26/* Free memory returned from module_alloc */ 27void module_free(struct module *mod, void *module_region) 28{ 29 vfree(module_region); 30} 31 32/* Transfer the section to the L1 memory */ 33int 34module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, 35 char *secstrings, struct module *mod) 36{ 37 Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; 38 void *dest; 39 40 for (s = sechdrs; s < sechdrs_end; ++s) { 41 const char *shname = secstrings + s->sh_name; 42 43 if (s->sh_size == 0) 44 continue; 45 46 if (!strcmp(".l1.text", shname) || 47 (!strcmp(".text", shname) && 48 (hdr->e_flags & EF_BFIN_CODE_IN_L1))) { 49 50 dest = l1_inst_sram_alloc(s->sh_size); 51 mod->arch.text_l1 = dest; 52 if (dest == NULL) { 53 pr_err("L1 inst memory allocation failed\n", 54 mod->name); 55 return -1; 56 } 57 dma_memcpy(dest, (void *)s->sh_addr, s->sh_size); 58 59 } else if (!strcmp(".l1.data", shname) || 60 (!strcmp(".data", shname) && 61 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) { 62 63 dest = l1_data_sram_alloc(s->sh_size); 64 mod->arch.data_a_l1 = dest; 65 if (dest == NULL) { 66 pr_err("L1 data memory allocation failed\n", 67 mod->name); 68 return -1; 69 } 70 memcpy(dest, (void *)s->sh_addr, s->sh_size); 71 72 } else if (!strcmp(".l1.bss", shname) || 73 (!strcmp(".bss", shname) && 74 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) { 75 76 dest = l1_data_sram_zalloc(s->sh_size); 77 mod->arch.bss_a_l1 = dest; 78 if (dest == NULL) { 79 pr_err("L1 data memory allocation failed\n", 80 mod->name); 81 return -1; 82 } 83 84 } else if (!strcmp(".l1.data.B", shname)) { 85 86 dest = l1_data_B_sram_alloc(s->sh_size); 87 mod->arch.data_b_l1 = dest; 88 if (dest == NULL) { 89 pr_err("L1 data memory allocation failed\n", 90 mod->name); 91 return -1; 92 } 93 memcpy(dest, (void *)s->sh_addr, s->sh_size); 94 95 } else if (!strcmp(".l1.bss.B", shname)) { 96 97 dest = l1_data_B_sram_alloc(s->sh_size); 98 mod->arch.bss_b_l1 = dest; 99 if (dest == NULL) { 100 pr_err("L1 data memory allocation failed\n", 101 mod->name); 102 return -1; 103 } 104 memset(dest, 0, s->sh_size); 105 106 } else if (!strcmp(".l2.text", shname) || 107 (!strcmp(".text", shname) && 108 (hdr->e_flags & EF_BFIN_CODE_IN_L2))) { 109 110 dest = l2_sram_alloc(s->sh_size); 111 mod->arch.text_l2 = dest; 112 if (dest == NULL) { 113 pr_err("L2 SRAM allocation failed\n", 114 mod->name); 115 return -1; 116 } 117 memcpy(dest, (void *)s->sh_addr, s->sh_size); 118 119 } else if (!strcmp(".l2.data", shname) || 120 (!strcmp(".data", shname) && 121 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) { 122 123 dest = l2_sram_alloc(s->sh_size); 124 mod->arch.data_l2 = dest; 125 if (dest == NULL) { 126 pr_err("L2 SRAM allocation failed\n", 127 mod->name); 128 return -1; 129 } 130 memcpy(dest, (void *)s->sh_addr, s->sh_size); 131 132 } else if (!strcmp(".l2.bss", shname) || 133 (!strcmp(".bss", shname) && 134 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) { 135 136 dest = l2_sram_zalloc(s->sh_size); 137 mod->arch.bss_l2 = dest; 138 if (dest == NULL) { 139 pr_err("L2 SRAM allocation failed\n", 140 mod->name); 141 return -1; 142 } 143 144 } else 145 continue; 146 147 s->sh_flags &= ~SHF_ALLOC; 148 s->sh_addr = (unsigned long)dest; 149 } 150 151 return 0; 152} 153 154int 155apply_relocate(Elf_Shdr * sechdrs, const char *strtab, 156 unsigned int symindex, unsigned int relsec, struct module *me) 157{ 158 pr_err(".rel unsupported\n", me->name); 159 return -ENOEXEC; 160} 161 162/*************************************************************************/ 163/* FUNCTION : apply_relocate_add */ 164/* ABSTRACT : Blackfin specific relocation handling for the loadable */ 165/* modules. Modules are expected to be .o files. */ 166/* Arithmetic relocations are handled. */ 167/* We do not expect LSETUP to be split and hence is not */ 168/* handled. */ 169/* R_BFIN_BYTE and R_BFIN_BYTE2 are also not handled as the */ 170/* gas does not generate it. */ 171/*************************************************************************/ 172int 173apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, 174 unsigned int symindex, unsigned int relsec, 175 struct module *mod) 176{ 177 unsigned int i; 178 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; 179 Elf32_Sym *sym; 180 unsigned long location, value, size; 181 182 pr_debug("applying relocate section %u to %u\n", mod->name, 183 relsec, sechdrs[relsec].sh_info); 184 185 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 186 /* This is where to make the change */ 187 location = sechdrs[sechdrs[relsec].sh_info].sh_addr + 188 rel[i].r_offset; 189 190 /* This is the symbol it is referring to. Note that all 191 undefined symbols have been resolved. */ 192 sym = (Elf32_Sym *) sechdrs[symindex].sh_addr 193 + ELF32_R_SYM(rel[i].r_info); 194 value = sym->st_value; 195 value += rel[i].r_addend; 196 197#ifdef CONFIG_SMP 198 if (location >= COREB_L1_DATA_A_START) { 199 pr_err("cannot relocate in L1: %u (SMP kernel)", 200 mod->name, ELF32_R_TYPE(rel[i].r_info)); 201 return -ENOEXEC; 202 } 203#endif 204 205 pr_debug("location is %lx, value is %lx type is %d\n", 206 mod->name, location, value, ELF32_R_TYPE(rel[i].r_info)); 207 208 switch (ELF32_R_TYPE(rel[i].r_info)) { 209 210 case R_BFIN_HUIMM16: 211 value >>= 16; 212 case R_BFIN_LUIMM16: 213 case R_BFIN_RIMM16: 214 size = 2; 215 break; 216 case R_BFIN_BYTE4_DATA: 217 size = 4; 218 break; 219 220 case R_BFIN_PCREL24: 221 case R_BFIN_PCREL24_JUMP_L: 222 case R_BFIN_PCREL12_JUMP: 223 case R_BFIN_PCREL12_JUMP_S: 224 case R_BFIN_PCREL10: 225 pr_err("unsupported relocation: %u (no -mlong-calls?)\n", 226 mod->name, ELF32_R_TYPE(rel[i].r_info)); 227 return -ENOEXEC; 228 229 default: 230 pr_err("unknown relocation: %u\n", mod->name, 231 ELF32_R_TYPE(rel[i].r_info)); 232 return -ENOEXEC; 233 } 234 235 switch (bfin_mem_access_type(location, size)) { 236 case BFIN_MEM_ACCESS_CORE: 237 case BFIN_MEM_ACCESS_CORE_ONLY: 238 memcpy((void *)location, &value, size); 239 break; 240 case BFIN_MEM_ACCESS_DMA: 241 dma_memcpy((void *)location, &value, size); 242 break; 243 case BFIN_MEM_ACCESS_ITEST: 244 isram_memcpy((void *)location, &value, size); 245 break; 246 default: 247 pr_err("invalid relocation for %#lx\n", 248 mod->name, location); 249 return -ENOEXEC; 250 } 251 } 252 253 return 0; 254} 255 256int 257module_finalize(const Elf_Ehdr * hdr, 258 const Elf_Shdr * sechdrs, struct module *mod) 259{ 260 unsigned int i, strindex = 0, symindex = 0; 261 char *secstrings; 262 long err = 0; 263 264 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 265 266 for (i = 1; i < hdr->e_shnum; i++) { 267 /* Internal symbols and strings. */ 268 if (sechdrs[i].sh_type == SHT_SYMTAB) { 269 symindex = i; 270 strindex = sechdrs[i].sh_link; 271 } 272 } 273 274 for (i = 1; i < hdr->e_shnum; i++) { 275 const char *strtab = (char *)sechdrs[strindex].sh_addr; 276 unsigned int info = sechdrs[i].sh_info; 277 const char *shname = secstrings + sechdrs[i].sh_name; 278 279 /* Not a valid relocation section? */ 280 if (info >= hdr->e_shnum) 281 continue; 282 283 /* Only support RELA relocation types */ 284 if (sechdrs[i].sh_type != SHT_RELA) 285 continue; 286 287 if (!strcmp(".rela.l2.text", shname) || 288 !strcmp(".rela.l1.text", shname) || 289 (!strcmp(".rela.text", shname) && 290 (hdr->e_flags & (EF_BFIN_CODE_IN_L1 | EF_BFIN_CODE_IN_L2)))) { 291 292 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab, 293 symindex, i, mod); 294 if (err < 0) 295 return -ENOEXEC; 296 } 297 } 298 299 return 0; 300} 301 302void module_arch_cleanup(struct module *mod) 303{ 304 l1_inst_sram_free(mod->arch.text_l1); 305 l1_data_A_sram_free(mod->arch.data_a_l1); 306 l1_data_A_sram_free(mod->arch.bss_a_l1); 307 l1_data_B_sram_free(mod->arch.data_b_l1); 308 l1_data_B_sram_free(mod->arch.bss_b_l1); 309 l2_sram_free(mod->arch.text_l2); 310 l2_sram_free(mod->arch.data_l2); 311 l2_sram_free(mod->arch.bss_l2); 312} 313