1a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer/*
2a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer * This file is subject to the terms and conditions of the GNU General Public
3a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer * License.  See the file COPYING in the main directory of this archive
4a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer * for more details.
5a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer */
6a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
7a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/moduleloader.h>
8a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/elf.h>
9a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/vmalloc.h>
10a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/fs.h>
11a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/string.h>
12a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#include <linux/kernel.h>
13a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
14a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#if 0
15a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#define DEBUGP printk
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
17a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#define DEBUGP(fmt...)
18a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#endif
19a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
20a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#ifdef CONFIG_MODULES
21a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
22a66af29876b086d8279b48515b83ced66803fb15Greg Ungererint apply_relocate(Elf32_Shdr *sechdrs,
23a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		   const char *strtab,
24a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		   unsigned int symindex,
25a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		   unsigned int relsec,
26a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		   struct module *me)
27a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{
28a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	unsigned int i;
29a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
30a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	Elf32_Sym *sym;
31a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	uint32_t *location;
32a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
33a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	DEBUGP("Applying relocate section %u to %u\n", relsec,
34a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	       sechdrs[relsec].sh_info);
35a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
36a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		/* This is where to make the change */
37a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
38a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			+ rel[i].r_offset;
39a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		/* This is the symbol it is referring to.  Note that all
40a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		   undefined symbols have been resolved.  */
41a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
42a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			+ ELF32_R_SYM(rel[i].r_info);
43a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
44a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		switch (ELF32_R_TYPE(rel[i].r_info)) {
45a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		case R_68K_32:
46a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			/* We add the value into the location given */
47a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			*location += sym->st_value;
48a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			break;
49a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		case R_68K_PC32:
50a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			/* Add the value, subtract its postition */
51a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			*location += sym->st_value - (uint32_t)location;
52a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			break;
53a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		default:
54a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
55a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			       me->name, ELF32_R_TYPE(rel[i].r_info));
56a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			return -ENOEXEC;
57a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		}
58a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	}
59a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	return 0;
60a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer}
61a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
62a66af29876b086d8279b48515b83ced66803fb15Greg Ungererint apply_relocate_add(Elf32_Shdr *sechdrs,
63a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		       const char *strtab,
64a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		       unsigned int symindex,
65a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		       unsigned int relsec,
66a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		       struct module *me)
67a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{
68a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	unsigned int i;
69a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
70a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	Elf32_Sym *sym;
71a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	uint32_t *location;
72a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
73a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
74a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	       sechdrs[relsec].sh_info);
75a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
76a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		/* This is where to make the change */
77a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
78a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			+ rel[i].r_offset;
79a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		/* This is the symbol it is referring to.  Note that all
80a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		   undefined symbols have been resolved.  */
81a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
82a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			+ ELF32_R_SYM(rel[i].r_info);
83a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
84a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		switch (ELF32_R_TYPE(rel[i].r_info)) {
85a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		case R_68K_32:
86a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			/* We add the value into the location given */
87a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			*location = rel[i].r_addend + sym->st_value;
88a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			break;
89a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		case R_68K_PC32:
90a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			/* Add the value, subtract its postition */
91a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
92a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			break;
93a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		default:
94a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
95a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			       me->name, ELF32_R_TYPE(rel[i].r_info));
96a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			return -ENOEXEC;
97a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		}
98a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	}
99a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	return 0;
100a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer}
101a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
102a66af29876b086d8279b48515b83ced66803fb15Greg Ungererint module_finalize(const Elf_Ehdr *hdr,
103a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		    const Elf_Shdr *sechdrs,
104a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		    struct module *mod)
105a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{
106a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
107a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	return 0;
108a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer}
109a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
110a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#endif /* CONFIG_MODULES */
111a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
112a66af29876b086d8279b48515b83ced66803fb15Greg Ungerervoid module_fixup(struct module *mod, struct m68k_fixup_info *start,
113a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		  struct m68k_fixup_info *end)
114a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer{
115a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer#ifdef CONFIG_MMU
116a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	struct m68k_fixup_info *fixup;
117a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer
118a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	for (fixup = start; fixup < end; fixup++) {
119a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		switch (fixup->type) {
120a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		case m68k_fixup_memoffset:
121a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			*(u32 *)fixup->addr = m68k_memoffset;
122a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			break;
123a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		case m68k_fixup_vnode_shift:
124a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
125a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer			break;
126a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer		}
127a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer	}
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
129a66af29876b086d8279b48515b83ced66803fb15Greg Ungerer}
130