xref: /openbmc/linux/arch/m68k/kernel/module.c (revision 1da177e4)
11da177e4SLinus Torvalds #include <linux/moduleloader.h>
21da177e4SLinus Torvalds #include <linux/elf.h>
31da177e4SLinus Torvalds #include <linux/vmalloc.h>
41da177e4SLinus Torvalds #include <linux/fs.h>
51da177e4SLinus Torvalds #include <linux/string.h>
61da177e4SLinus Torvalds #include <linux/kernel.h>
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #if 0
91da177e4SLinus Torvalds #define DEBUGP printk
101da177e4SLinus Torvalds #else
111da177e4SLinus Torvalds #define DEBUGP(fmt...)
121da177e4SLinus Torvalds #endif
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds void *module_alloc(unsigned long size)
151da177e4SLinus Torvalds {
161da177e4SLinus Torvalds 	if (size == 0)
171da177e4SLinus Torvalds 		return NULL;
181da177e4SLinus Torvalds 	return vmalloc(size);
191da177e4SLinus Torvalds }
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds /* Free memory returned from module_alloc */
231da177e4SLinus Torvalds void module_free(struct module *mod, void *module_region)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds 	vfree(module_region);
261da177e4SLinus Torvalds 	/* FIXME: If module_region == mod->init_region, trim exception
271da177e4SLinus Torvalds            table entries. */
281da177e4SLinus Torvalds }
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds /* We don't need anything special. */
311da177e4SLinus Torvalds int module_frob_arch_sections(Elf_Ehdr *hdr,
321da177e4SLinus Torvalds 			      Elf_Shdr *sechdrs,
331da177e4SLinus Torvalds 			      char *secstrings,
341da177e4SLinus Torvalds 			      struct module *mod)
351da177e4SLinus Torvalds {
361da177e4SLinus Torvalds 	return 0;
371da177e4SLinus Torvalds }
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds int apply_relocate(Elf32_Shdr *sechdrs,
401da177e4SLinus Torvalds 		   const char *strtab,
411da177e4SLinus Torvalds 		   unsigned int symindex,
421da177e4SLinus Torvalds 		   unsigned int relsec,
431da177e4SLinus Torvalds 		   struct module *me)
441da177e4SLinus Torvalds {
451da177e4SLinus Torvalds 	unsigned int i;
461da177e4SLinus Torvalds 	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
471da177e4SLinus Torvalds 	Elf32_Sym *sym;
481da177e4SLinus Torvalds 	uint32_t *location;
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds 	DEBUGP("Applying relocate section %u to %u\n", relsec,
511da177e4SLinus Torvalds 	       sechdrs[relsec].sh_info);
521da177e4SLinus Torvalds 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
531da177e4SLinus Torvalds 		/* This is where to make the change */
541da177e4SLinus Torvalds 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
551da177e4SLinus Torvalds 			+ rel[i].r_offset;
561da177e4SLinus Torvalds 		/* This is the symbol it is referring to.  Note that all
571da177e4SLinus Torvalds 		   undefined symbols have been resolved.  */
581da177e4SLinus Torvalds 		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
591da177e4SLinus Torvalds 			+ ELF32_R_SYM(rel[i].r_info);
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds 		switch (ELF32_R_TYPE(rel[i].r_info)) {
621da177e4SLinus Torvalds 		case R_68K_32:
631da177e4SLinus Torvalds 			/* We add the value into the location given */
641da177e4SLinus Torvalds 			*location += sym->st_value;
651da177e4SLinus Torvalds 			break;
661da177e4SLinus Torvalds 		case R_68K_PC32:
671da177e4SLinus Torvalds 			/* Add the value, subtract its postition */
681da177e4SLinus Torvalds 			*location += sym->st_value - (uint32_t)location;
691da177e4SLinus Torvalds 			break;
701da177e4SLinus Torvalds 		default:
711da177e4SLinus Torvalds 			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
721da177e4SLinus Torvalds 			       me->name, ELF32_R_TYPE(rel[i].r_info));
731da177e4SLinus Torvalds 			return -ENOEXEC;
741da177e4SLinus Torvalds 		}
751da177e4SLinus Torvalds 	}
761da177e4SLinus Torvalds 	return 0;
771da177e4SLinus Torvalds }
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds int apply_relocate_add(Elf32_Shdr *sechdrs,
801da177e4SLinus Torvalds 		       const char *strtab,
811da177e4SLinus Torvalds 		       unsigned int symindex,
821da177e4SLinus Torvalds 		       unsigned int relsec,
831da177e4SLinus Torvalds 		       struct module *me)
841da177e4SLinus Torvalds {
851da177e4SLinus Torvalds 	unsigned int i;
861da177e4SLinus Torvalds 	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
871da177e4SLinus Torvalds 	Elf32_Sym *sym;
881da177e4SLinus Torvalds 	uint32_t *location;
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
911da177e4SLinus Torvalds 	       sechdrs[relsec].sh_info);
921da177e4SLinus Torvalds 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
931da177e4SLinus Torvalds 		/* This is where to make the change */
941da177e4SLinus Torvalds 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
951da177e4SLinus Torvalds 			+ rel[i].r_offset;
961da177e4SLinus Torvalds 		/* This is the symbol it is referring to.  Note that all
971da177e4SLinus Torvalds 		   undefined symbols have been resolved.  */
981da177e4SLinus Torvalds 		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
991da177e4SLinus Torvalds 			+ ELF32_R_SYM(rel[i].r_info);
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 		switch (ELF32_R_TYPE(rel[i].r_info)) {
1021da177e4SLinus Torvalds 		case R_68K_32:
1031da177e4SLinus Torvalds 			/* We add the value into the location given */
1041da177e4SLinus Torvalds 			*location = rel[i].r_addend + sym->st_value;
1051da177e4SLinus Torvalds 			break;
1061da177e4SLinus Torvalds 		case R_68K_PC32:
1071da177e4SLinus Torvalds 			/* Add the value, subtract its postition */
1081da177e4SLinus Torvalds 			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
1091da177e4SLinus Torvalds 			break;
1101da177e4SLinus Torvalds 		default:
1111da177e4SLinus Torvalds 			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
1121da177e4SLinus Torvalds 			       me->name, ELF32_R_TYPE(rel[i].r_info));
1131da177e4SLinus Torvalds 			return -ENOEXEC;
1141da177e4SLinus Torvalds 		}
1151da177e4SLinus Torvalds 	}
1161da177e4SLinus Torvalds 	return 0;
1171da177e4SLinus Torvalds }
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds int module_finalize(const Elf_Ehdr *hdr,
1201da177e4SLinus Torvalds 		    const Elf_Shdr *sechdrs,
1211da177e4SLinus Torvalds 		    struct module *me)
1221da177e4SLinus Torvalds {
1231da177e4SLinus Torvalds 	return 0;
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds void module_arch_cleanup(struct module *mod)
1271da177e4SLinus Torvalds {
1281da177e4SLinus Torvalds }
129