xref: /openbmc/linux/arch/m68k/kernel/module.c (revision 1da177e4)
1 #include <linux/moduleloader.h>
2 #include <linux/elf.h>
3 #include <linux/vmalloc.h>
4 #include <linux/fs.h>
5 #include <linux/string.h>
6 #include <linux/kernel.h>
7 
8 #if 0
9 #define DEBUGP printk
10 #else
11 #define DEBUGP(fmt...)
12 #endif
13 
14 void *module_alloc(unsigned long size)
15 {
16 	if (size == 0)
17 		return NULL;
18 	return vmalloc(size);
19 }
20 
21 
22 /* Free memory returned from module_alloc */
23 void module_free(struct module *mod, void *module_region)
24 {
25 	vfree(module_region);
26 	/* FIXME: If module_region == mod->init_region, trim exception
27            table entries. */
28 }
29 
30 /* We don't need anything special. */
31 int module_frob_arch_sections(Elf_Ehdr *hdr,
32 			      Elf_Shdr *sechdrs,
33 			      char *secstrings,
34 			      struct module *mod)
35 {
36 	return 0;
37 }
38 
39 int apply_relocate(Elf32_Shdr *sechdrs,
40 		   const char *strtab,
41 		   unsigned int symindex,
42 		   unsigned int relsec,
43 		   struct module *me)
44 {
45 	unsigned int i;
46 	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
47 	Elf32_Sym *sym;
48 	uint32_t *location;
49 
50 	DEBUGP("Applying relocate section %u to %u\n", relsec,
51 	       sechdrs[relsec].sh_info);
52 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
53 		/* This is where to make the change */
54 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
55 			+ rel[i].r_offset;
56 		/* This is the symbol it is referring to.  Note that all
57 		   undefined symbols have been resolved.  */
58 		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
59 			+ ELF32_R_SYM(rel[i].r_info);
60 
61 		switch (ELF32_R_TYPE(rel[i].r_info)) {
62 		case R_68K_32:
63 			/* We add the value into the location given */
64 			*location += sym->st_value;
65 			break;
66 		case R_68K_PC32:
67 			/* Add the value, subtract its postition */
68 			*location += sym->st_value - (uint32_t)location;
69 			break;
70 		default:
71 			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
72 			       me->name, ELF32_R_TYPE(rel[i].r_info));
73 			return -ENOEXEC;
74 		}
75 	}
76 	return 0;
77 }
78 
79 int apply_relocate_add(Elf32_Shdr *sechdrs,
80 		       const char *strtab,
81 		       unsigned int symindex,
82 		       unsigned int relsec,
83 		       struct module *me)
84 {
85 	unsigned int i;
86 	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
87 	Elf32_Sym *sym;
88 	uint32_t *location;
89 
90 	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
91 	       sechdrs[relsec].sh_info);
92 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
93 		/* This is where to make the change */
94 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
95 			+ rel[i].r_offset;
96 		/* This is the symbol it is referring to.  Note that all
97 		   undefined symbols have been resolved.  */
98 		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
99 			+ ELF32_R_SYM(rel[i].r_info);
100 
101 		switch (ELF32_R_TYPE(rel[i].r_info)) {
102 		case R_68K_32:
103 			/* We add the value into the location given */
104 			*location = rel[i].r_addend + sym->st_value;
105 			break;
106 		case R_68K_PC32:
107 			/* Add the value, subtract its postition */
108 			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
109 			break;
110 		default:
111 			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
112 			       me->name, ELF32_R_TYPE(rel[i].r_info));
113 			return -ENOEXEC;
114 		}
115 	}
116 	return 0;
117 }
118 
119 int module_finalize(const Elf_Ehdr *hdr,
120 		    const Elf_Shdr *sechdrs,
121 		    struct module *me)
122 {
123 	return 0;
124 }
125 
126 void module_arch_cleanup(struct module *mod)
127 {
128 }
129