GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / blackfin / kernel / module.c
blob05bc762f4b5b78348019ead9bb406faffbfdbd97
1 /*
2 * Copyright 2004-2009 Analog Devices Inc.
4 * Licensed under the GPL-2 or later
5 */
7 #define pr_fmt(fmt) "module %s: " fmt
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>
19 void *module_alloc(unsigned long size)
21 if (size == 0)
22 return NULL;
23 return vmalloc(size);
26 /* Free memory returned from module_alloc */
27 void module_free(struct module *mod, void *module_region)
29 vfree(module_region);
32 /* Transfer the section to the L1 memory */
33 int
34 module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
35 char *secstrings, struct module *mod)
37 Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
38 void *dest;
40 for (s = sechdrs; s < sechdrs_end; ++s) {
41 const char *shname = secstrings + s->sh_name;
43 if (s->sh_size == 0)
44 continue;
46 if (!strcmp(".l1.text", shname) ||
47 (!strcmp(".text", shname) &&
48 (hdr->e_flags & EF_BFIN_CODE_IN_L1))) {
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;
57 dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
59 } else if (!strcmp(".l1.data", shname) ||
60 (!strcmp(".data", shname) &&
61 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
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;
70 memcpy(dest, (void *)s->sh_addr, s->sh_size);
72 } else if (!strcmp(".l1.bss", shname) ||
73 (!strcmp(".bss", shname) &&
74 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
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;
84 } else if (!strcmp(".l1.data.B", shname)) {
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;
93 memcpy(dest, (void *)s->sh_addr, s->sh_size);
95 } else if (!strcmp(".l1.bss.B", shname)) {
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;
104 memset(dest, 0, s->sh_size);
106 } else if (!strcmp(".l2.text", shname) ||
107 (!strcmp(".text", shname) &&
108 (hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
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;
117 memcpy(dest, (void *)s->sh_addr, s->sh_size);
119 } else if (!strcmp(".l2.data", shname) ||
120 (!strcmp(".data", shname) &&
121 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
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;
130 memcpy(dest, (void *)s->sh_addr, s->sh_size);
132 } else if (!strcmp(".l2.bss", shname) ||
133 (!strcmp(".bss", shname) &&
134 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
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;
144 } else
145 continue;
147 s->sh_flags &= ~SHF_ALLOC;
148 s->sh_addr = (unsigned long)dest;
151 return 0;
155 apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
156 unsigned int symindex, unsigned int relsec, struct module *me)
158 pr_err(".rel unsupported\n", me->name);
159 return -ENOEXEC;
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 /*************************************************************************/
173 apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
174 unsigned int symindex, unsigned int relsec,
175 struct module *mod)
177 unsigned int i;
178 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
179 Elf32_Sym *sym;
180 unsigned long location, value, size;
182 pr_debug("applying relocate section %u to %u\n", mod->name,
183 relsec, sechdrs[relsec].sh_info);
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;
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;
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;
203 #endif
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));
208 switch (ELF32_R_TYPE(rel[i].r_info)) {
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;
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;
229 default:
230 pr_err("unknown relocation: %u\n", mod->name,
231 ELF32_R_TYPE(rel[i].r_info));
232 return -ENOEXEC;
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;
253 return 0;
257 module_finalize(const Elf_Ehdr * hdr,
258 const Elf_Shdr * sechdrs, struct module *mod)
260 unsigned int i, strindex = 0, symindex = 0;
261 char *secstrings;
262 long err = 0;
264 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
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;
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;
279 /* Not a valid relocation section? */
280 if (info >= hdr->e_shnum)
281 continue;
283 /* Only support RELA relocation types */
284 if (sechdrs[i].sh_type != SHT_RELA)
285 continue;
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)))) {
292 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
293 symindex, i, mod);
294 if (err < 0)
295 return -ENOEXEC;
299 return 0;
302 void module_arch_cleanup(struct module *mod)
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);