GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / mn10300 / kernel / module.c
blobd5bbb0918952faa4901d26c00a09e282914b4b3c
1 /* MN10300 Kernel module helper routines
3 * Copyright (C) 2007, 2008, 2009 Red Hat, Inc. All Rights Reserved.
4 * Written by Mark Salter (msalter@redhat.com)
5 * - Derived from arch/i386/kernel/module.c
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public Licence as published by
9 * the Free Software Foundation; either version 2 of the Licence, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public Licence for more details.
17 * You should have received a copy of the GNU General Public Licence
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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>
27 #include <linux/bug.h>
29 #define DEBUGP(fmt, ...)
32 * allocate storage for a module
34 void *module_alloc(unsigned long size)
36 if (size == 0)
37 return NULL;
38 return vmalloc_exec(size);
42 * free memory returned from module_alloc()
44 void module_free(struct module *mod, void *module_region)
46 vfree(module_region);
50 * allow the arch to fix up the section table
51 * - we don't need anything special
53 int module_frob_arch_sections(Elf_Ehdr *hdr,
54 Elf_Shdr *sechdrs,
55 char *secstrings,
56 struct module *mod)
58 return 0;
61 static void reloc_put16(uint8_t *p, uint32_t val)
63 p[0] = val & 0xff;
64 p[1] = (val >> 8) & 0xff;
67 static void reloc_put24(uint8_t *p, uint32_t val)
69 reloc_put16(p, val);
70 p[2] = (val >> 16) & 0xff;
73 static void reloc_put32(uint8_t *p, uint32_t val)
75 reloc_put16(p, val);
76 reloc_put16(p+2, val >> 16);
80 * apply a REL relocation
82 int apply_relocate(Elf32_Shdr *sechdrs,
83 const char *strtab,
84 unsigned int symindex,
85 unsigned int relsec,
86 struct module *me)
88 printk(KERN_ERR "module %s: RELOCATION unsupported\n",
89 me->name);
90 return -ENOEXEC;
94 * apply a RELA relocation
96 int apply_relocate_add(Elf32_Shdr *sechdrs,
97 const char *strtab,
98 unsigned int symindex,
99 unsigned int relsec,
100 struct module *me)
102 unsigned int i, sym_diff_seen = 0;
103 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
104 Elf32_Sym *sym;
105 Elf32_Addr relocation, sym_diff_val = 0;
106 uint8_t *location;
107 uint32_t value;
109 DEBUGP("Applying relocate section %u to %u\n",
110 relsec, sechdrs[relsec].sh_info);
112 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
113 /* this is where to make the change */
114 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
115 + rel[i].r_offset;
117 /* this is the symbol the relocation is referring to (note that
118 * all undefined symbols have been resolved by the caller) */
119 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
120 + ELF32_R_SYM(rel[i].r_info);
122 /* this is the adjustment to be made */
123 relocation = sym->st_value + rel[i].r_addend;
125 if (sym_diff_seen) {
126 switch (ELF32_R_TYPE(rel[i].r_info)) {
127 case R_MN10300_32:
128 case R_MN10300_24:
129 case R_MN10300_16:
130 case R_MN10300_8:
131 relocation -= sym_diff_val;
132 sym_diff_seen = 0;
133 break;
134 default:
135 printk(KERN_ERR "module %s: Unexpected SYM_DIFF relocation: %u\n",
136 me->name, ELF32_R_TYPE(rel[i].r_info));
137 return -ENOEXEC;
141 switch (ELF32_R_TYPE(rel[i].r_info)) {
142 /* for the first four relocation types, we simply
143 * store the adjustment at the location given */
144 case R_MN10300_32:
145 reloc_put32(location, relocation);
146 break;
147 case R_MN10300_24:
148 reloc_put24(location, relocation);
149 break;
150 case R_MN10300_16:
151 reloc_put16(location, relocation);
152 break;
153 case R_MN10300_8:
154 *location = relocation;
155 break;
157 /* for the next three relocation types, we write the
158 * adjustment with the address subtracted over the
159 * value at the location given */
160 case R_MN10300_PCREL32:
161 value = relocation - (uint32_t) location;
162 reloc_put32(location, value);
163 break;
164 case R_MN10300_PCREL16:
165 value = relocation - (uint32_t) location;
166 reloc_put16(location, value);
167 break;
168 case R_MN10300_PCREL8:
169 *location = relocation - (uint32_t) location;
170 break;
172 case R_MN10300_SYM_DIFF:
173 /* This is used to adjust the next reloc as required
174 * by relaxation. */
175 sym_diff_seen = 1;
176 sym_diff_val = sym->st_value;
177 break;
179 case R_MN10300_ALIGN:
180 /* Just ignore the ALIGN relocs.
181 * Only interesting if kernel performed relaxation. */
182 continue;
184 default:
185 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
186 me->name, ELF32_R_TYPE(rel[i].r_info));
187 return -ENOEXEC;
190 if (sym_diff_seen) {
191 printk(KERN_ERR "module %s: Nothing follows SYM_DIFF relocation: %u\n",
192 me->name, ELF32_R_TYPE(rel[i].r_info));
193 return -ENOEXEC;
195 return 0;
199 * finish loading the module
201 int module_finalize(const Elf_Ehdr *hdr,
202 const Elf_Shdr *sechdrs,
203 struct module *me)
205 return 0;
209 * finish clearing the module
211 void module_arch_cleanup(struct module *mod)