• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/m68k/kernel/
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#include <linux/moduleloader.h>
8#include <linux/elf.h>
9#include <linux/vmalloc.h>
10#include <linux/fs.h>
11#include <linux/string.h>
12#include <linux/kernel.h>
13
14#define DEBUGP(fmt...)
15
16#ifdef CONFIG_MODULES
17
18void *module_alloc(unsigned long size)
19{
20	if (size == 0)
21		return NULL;
22	return vmalloc(size);
23}
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/* We don't need anything special. */
33int module_frob_arch_sections(Elf_Ehdr *hdr,
34			      Elf_Shdr *sechdrs,
35			      char *secstrings,
36			      struct module *mod)
37{
38	return 0;
39}
40
41int apply_relocate(Elf32_Shdr *sechdrs,
42		   const char *strtab,
43		   unsigned int symindex,
44		   unsigned int relsec,
45		   struct module *me)
46{
47	unsigned int i;
48	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
49	Elf32_Sym *sym;
50	uint32_t *location;
51
52	DEBUGP("Applying relocate section %u to %u\n", relsec,
53	       sechdrs[relsec].sh_info);
54	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
55		/* This is where to make the change */
56		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
57			+ rel[i].r_offset;
58		/* This is the symbol it is referring to.  Note that all
59		   undefined symbols have been resolved.  */
60		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
61			+ ELF32_R_SYM(rel[i].r_info);
62
63		switch (ELF32_R_TYPE(rel[i].r_info)) {
64		case R_68K_32:
65			/* We add the value into the location given */
66			*location += sym->st_value;
67			break;
68		case R_68K_PC32:
69			/* Add the value, subtract its postition */
70			*location += sym->st_value - (uint32_t)location;
71			break;
72		default:
73			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
74			       me->name, ELF32_R_TYPE(rel[i].r_info));
75			return -ENOEXEC;
76		}
77	}
78	return 0;
79}
80
81int apply_relocate_add(Elf32_Shdr *sechdrs,
82		       const char *strtab,
83		       unsigned int symindex,
84		       unsigned int relsec,
85		       struct module *me)
86{
87	unsigned int i;
88	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
89	Elf32_Sym *sym;
90	uint32_t *location;
91
92	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
93	       sechdrs[relsec].sh_info);
94	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
95		/* This is where to make the change */
96		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
97			+ rel[i].r_offset;
98		/* This is the symbol it is referring to.  Note that all
99		   undefined symbols have been resolved.  */
100		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
101			+ ELF32_R_SYM(rel[i].r_info);
102
103		switch (ELF32_R_TYPE(rel[i].r_info)) {
104		case R_68K_32:
105			/* We add the value into the location given */
106			*location = rel[i].r_addend + sym->st_value;
107			break;
108		case R_68K_PC32:
109			/* Add the value, subtract its postition */
110			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
111			break;
112		default:
113			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
114			       me->name, ELF32_R_TYPE(rel[i].r_info));
115			return -ENOEXEC;
116		}
117	}
118	return 0;
119}
120
121int module_finalize(const Elf_Ehdr *hdr,
122		    const Elf_Shdr *sechdrs,
123		    struct module *mod)
124{
125	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
126
127	return 0;
128}
129
130void module_arch_cleanup(struct module *mod)
131{
132}
133
134#endif /* CONFIG_MODULES */
135
136void module_fixup(struct module *mod, struct m68k_fixup_info *start,
137		  struct m68k_fixup_info *end)
138{
139	struct m68k_fixup_info *fixup;
140
141	for (fixup = start; fixup < end; fixup++) {
142		switch (fixup->type) {
143		case m68k_fixup_memoffset:
144			*(u32 *)fixup->addr = m68k_memoffset;
145			break;
146		case m68k_fixup_vnode_shift:
147			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
148			break;
149		}
150	}
151}
152