xref: /linux-6.15/arch/microblaze/kernel/module.c (revision 4dc7ccf7)
1 /*
2  * Copyright (C) 2007-2009 Michal Simek <[email protected]>
3  * Copyright (C) 2007-2009 PetaLogix
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #include <linux/module.h>
11 #include <linux/moduleloader.h>
12 #include <linux/kernel.h>
13 #include <linux/elf.h>
14 #include <linux/vmalloc.h>
15 #include <linux/fs.h>
16 #include <linux/string.h>
17 
18 #include <asm/pgtable.h>
19 
20 void *module_alloc(unsigned long size)
21 {
22 	void *ret;
23 	ret = (size == 0) ? NULL : vmalloc(size);
24 	pr_debug("module_alloc (%08lx@%08lx)\n", size, (unsigned long int)ret);
25 	return ret;
26 }
27 
28 void module_free(struct module *module, void *region)
29 {
30 	pr_debug("module_free(%s,%08lx)\n", module->name,
31 					(unsigned long)region);
32 	vfree(region);
33 }
34 
35 int module_frob_arch_sections(Elf_Ehdr *hdr,
36 				Elf_Shdr *sechdrs,
37 				char *secstrings,
38 				struct module *mod)
39 {
40 	return 0;
41 }
42 
43 int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
44 	unsigned int symindex, unsigned int relsec, struct module *module)
45 {
46 	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
47 		module->name);
48 	return -ENOEXEC;
49 }
50 
51 int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
52 	unsigned int symindex, unsigned int relsec, struct module *module)
53 {
54 
55 	unsigned int i;
56 	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
57 	Elf32_Sym *sym;
58 	unsigned long int *location;
59 	unsigned long int value;
60 #if __GNUC__ < 4
61 	unsigned long int old_value;
62 #endif
63 
64 	pr_debug("Applying add relocation section %u to %u\n",
65 		relsec, sechdrs[relsec].sh_info);
66 
67 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
68 
69 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr +
70 				rela[i].r_offset;
71 		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr +
72 			ELF32_R_SYM(rela[i].r_info);
73 		value = sym->st_value + rela[i].r_addend;
74 
75 		switch (ELF32_R_TYPE(rela[i].r_info)) {
76 
77 		/*
78 		 * Be careful! mb-gcc / mb-ld splits the relocs between the
79 		 * text and the reloc table. In general this means we must
80 		 * read the current contents of (*location), add any offset
81 		 * then store the result back in
82 		 */
83 
84 		case R_MICROBLAZE_32:
85 #if __GNUC__ < 4
86 			old_value = *location;
87 			*location = value + old_value;
88 
89 			pr_debug("R_MICROBLAZE_32 (%08lx->%08lx)\n",
90 				old_value, value);
91 #else
92 			*location = value;
93 #endif
94 			break;
95 
96 		case R_MICROBLAZE_64:
97 #if __GNUC__ < 4
98 			/* Split relocs only required/used pre gcc4.1.1 */
99 			old_value = ((location[0] & 0x0000FFFF) << 16) |
100 					(location[1] & 0x0000FFFF);
101 			value += old_value;
102 #endif
103 			location[0] = (location[0] & 0xFFFF0000) |
104 					(value >> 16);
105 			location[1] = (location[1] & 0xFFFF0000) |
106 					(value & 0xFFFF);
107 #if __GNUC__ < 4
108 			pr_debug("R_MICROBLAZE_64 (%08lx->%08lx)\n",
109 				old_value, value);
110 #endif
111 			break;
112 
113 		case R_MICROBLAZE_64_PCREL:
114 #if __GNUC__ < 4
115 			old_value = (location[0] & 0xFFFF) << 16 |
116 				(location[1] & 0xFFFF);
117 			value -= old_value;
118 #endif
119 			value -= (unsigned long int)(location) + 4;
120 			location[0] = (location[0] & 0xFFFF0000) |
121 					(value >> 16);
122 			location[1] = (location[1] & 0xFFFF0000) |
123 					(value & 0xFFFF);
124 			pr_debug("R_MICROBLAZE_64_PCREL (%08lx)\n",
125 				value);
126 			break;
127 
128 		case R_MICROBLAZE_32_PCREL_LO:
129 			pr_debug("R_MICROBLAZE_32_PCREL_LO\n");
130 			break;
131 
132 		case R_MICROBLAZE_64_NONE:
133 			pr_debug("R_MICROBLAZE_NONE\n");
134 			break;
135 
136 		case R_MICROBLAZE_NONE:
137 			pr_debug("R_MICROBLAZE_NONE\n");
138 			break;
139 
140 		default:
141 			printk(KERN_ERR "module %s: "
142 				"Unknown relocation: %u\n",
143 				module->name,
144 				ELF32_R_TYPE(rela[i].r_info));
145 			return -ENOEXEC;
146 		}
147 	}
148 	return 0;
149 }
150 
151 int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
152 		struct module *module)
153 {
154 	return 0;
155 }
156 
157 void module_arch_cleanup(struct module *mod)
158 {
159 }
160