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