MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / nios2nommu / kernel / module.c
blob99b270fe7aade1b71ea0449e10b8e203c32f6089
1 /* Kernel module help for Nios2.
2 Copyright (C) 2004 Microtronix Datacom Ltd.
3 Copyright (C) 2001,03 Rusty Russell
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 Written by Wentao Xu <xuwentao@microtronix.com>
21 #include <linux/moduleloader.h>
22 #include <linux/elf.h>
23 #include <linux/vmalloc.h>
24 #include <linux/fs.h>
25 #include <linux/string.h>
26 #include <linux/kernel.h>
28 #if 0
29 #define DEBUGP printk
30 #else
31 #define DEBUGP(fmt , ...)
32 #endif
34 void *module_alloc(unsigned long size)
36 if (size == 0)
37 return NULL;
38 return vmalloc(size);
42 /* Free memory returned from module_alloc */
43 void module_free(struct module *mod, void *module_region)
45 vfree(module_region);
46 /* FIXME: If module_region == mod->init_region, trim exception
47 table entries. */
50 /* We don't need anything special. */
51 int module_frob_arch_sections(Elf_Ehdr *hdr,
52 Elf_Shdr *sechdrs,
53 char *secstrings,
54 struct module *mod)
56 return 0;
59 int apply_relocate(Elf32_Shdr *sechdrs,
60 const char *strtab,
61 unsigned int symindex,
62 unsigned int relsec,
63 struct module *me)
65 printk(KERN_ERR "module %s: NO-ADD RELOCATION unsupported\n",
66 me->name);
67 return -ENOEXEC;
71 int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab,
72 unsigned int symindex, unsigned int relsec,
73 struct module *mod)
75 unsigned int i;
76 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
78 DEBUGP ("Applying relocate section %u to %u\n", relsec,
79 sechdrs[relsec].sh_info);
81 for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
82 /* This is where to make the change */
83 uint32_t word;
84 uint32_t *loc
85 = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
86 + rela[i].r_offset);
87 /* This is the symbol it is referring to. Note that all
88 undefined symbols have been resolved. */
89 Elf32_Sym *sym
90 = ((Elf32_Sym *)sechdrs[symindex].sh_addr
91 + ELF32_R_SYM (rela[i].r_info));
92 uint32_t v = sym->st_value + rela[i].r_addend;
94 switch (ELF32_R_TYPE (rela[i].r_info)) {
95 case R_NIOS2_NONE:
96 break;
98 case R_NIOS2_BFD_RELOC_32:
99 *loc += v;
100 break;
102 case R_NIOS2_PCREL16:
103 v -= (uint32_t)loc + 4;
104 if ((int32_t)v > 0x7fff ||
105 (int32_t)v < -(int32_t)0x8000) {
106 printk(KERN_ERR
107 "module %s: relocation overflow\n",
108 mod->name);
109 return -ENOEXEC;
111 word = *loc;
112 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
113 break;
115 case R_NIOS2_CALL26:
116 if (v & 3) {
117 printk(KERN_ERR
118 "module %s: dangerous relocation\n",
119 mod->name);
120 return -ENOEXEC;
122 if ((v >> 28) != ((uint32_t)loc >> 28)) {
123 printk(KERN_ERR
124 "module %s: relocation overflow\n",
125 mod->name);
126 return -ENOEXEC;
128 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
129 break;
131 case R_NIOS2_HI16:
132 word = *loc;
133 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
134 (word & 0x3f);
135 break;
137 case R_NIOS2_LO16:
138 word = *loc;
139 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
140 (word & 0x3f);
141 break;
143 case R_NIOS2_HIADJ16:
145 Elf32_Addr word2;
147 word = *loc;
148 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
149 *loc = ((((word >> 22) << 16) | word2) << 6) |
150 (word & 0x3f);
152 break;
154 default:
155 printk (KERN_ERR "module %s: Unknown reloc: %u\n",
156 mod->name, ELF32_R_TYPE (rela[i].r_info));
157 return -ENOEXEC;
161 return 0;
164 int module_finalize(const Elf_Ehdr *hdr,
165 const Elf_Shdr *sechdrs,
166 struct module *me)
168 return 0;
171 void module_arch_cleanup(struct module *mod)