PageRenderTime 22ms CodeModel.GetById 11ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 0ms

/arch/m68k/kernel/module.c

https://bitbucket.org/cresqo/cm7-p500-kernel
C | 155 lines | 119 code | 19 blank | 17 comment | 8 complexity | 7ee5ccf9a9df4a46a96a05674fc801aa MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  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#if 0
 15#define DEBUGP printk
 16#else
 17#define DEBUGP(fmt...)
 18#endif
 19
 20#ifdef CONFIG_MODULES
 21
 22void *module_alloc(unsigned long size)
 23{
 24	if (size == 0)
 25		return NULL;
 26	return vmalloc(size);
 27}
 28
 29
 30/* Free memory returned from module_alloc */
 31void module_free(struct module *mod, void *module_region)
 32{
 33	vfree(module_region);
 34}
 35
 36/* We don't need anything special. */
 37int module_frob_arch_sections(Elf_Ehdr *hdr,
 38			      Elf_Shdr *sechdrs,
 39			      char *secstrings,
 40			      struct module *mod)
 41{
 42	return 0;
 43}
 44
 45int apply_relocate(Elf32_Shdr *sechdrs,
 46		   const char *strtab,
 47		   unsigned int symindex,
 48		   unsigned int relsec,
 49		   struct module *me)
 50{
 51	unsigned int i;
 52	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
 53	Elf32_Sym *sym;
 54	uint32_t *location;
 55
 56	DEBUGP("Applying relocate section %u to %u\n", relsec,
 57	       sechdrs[relsec].sh_info);
 58	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
 59		/* This is where to make the change */
 60		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
 61			+ rel[i].r_offset;
 62		/* This is the symbol it is referring to.  Note that all
 63		   undefined symbols have been resolved.  */
 64		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
 65			+ ELF32_R_SYM(rel[i].r_info);
 66
 67		switch (ELF32_R_TYPE(rel[i].r_info)) {
 68		case R_68K_32:
 69			/* We add the value into the location given */
 70			*location += sym->st_value;
 71			break;
 72		case R_68K_PC32:
 73			/* Add the value, subtract its postition */
 74			*location += sym->st_value - (uint32_t)location;
 75			break;
 76		default:
 77			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
 78			       me->name, ELF32_R_TYPE(rel[i].r_info));
 79			return -ENOEXEC;
 80		}
 81	}
 82	return 0;
 83}
 84
 85int apply_relocate_add(Elf32_Shdr *sechdrs,
 86		       const char *strtab,
 87		       unsigned int symindex,
 88		       unsigned int relsec,
 89		       struct module *me)
 90{
 91	unsigned int i;
 92	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
 93	Elf32_Sym *sym;
 94	uint32_t *location;
 95
 96	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
 97	       sechdrs[relsec].sh_info);
 98	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
 99		/* This is where to make the change */
100		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
101			+ rel[i].r_offset;
102		/* This is the symbol it is referring to.  Note that all
103		   undefined symbols have been resolved.  */
104		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
105			+ ELF32_R_SYM(rel[i].r_info);
106
107		switch (ELF32_R_TYPE(rel[i].r_info)) {
108		case R_68K_32:
109			/* We add the value into the location given */
110			*location = rel[i].r_addend + sym->st_value;
111			break;
112		case R_68K_PC32:
113			/* Add the value, subtract its postition */
114			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
115			break;
116		default:
117			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
118			       me->name, ELF32_R_TYPE(rel[i].r_info));
119			return -ENOEXEC;
120		}
121	}
122	return 0;
123}
124
125int module_finalize(const Elf_Ehdr *hdr,
126		    const Elf_Shdr *sechdrs,
127		    struct module *mod)
128{
129	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
130
131	return 0;
132}
133
134void module_arch_cleanup(struct module *mod)
135{
136}
137
138#endif /* CONFIG_MODULES */
139
140void module_fixup(struct module *mod, struct m68k_fixup_info *start,
141		  struct m68k_fixup_info *end)
142{
143	struct m68k_fixup_info *fixup;
144
145	for (fixup = start; fixup < end; fixup++) {
146		switch (fixup->type) {
147		case m68k_fixup_memoffset:
148			*(u32 *)fixup->addr = m68k_memoffset;
149			break;
150		case m68k_fixup_vnode_shift:
151			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
152			break;
153		}
154	}
155}