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