2011-03-22 13:39:27 +10:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of this archive
* for more details .
*/
2005-04-16 15:20:36 -07:00
# include <linux/moduleloader.h>
# include <linux/elf.h>
# include <linux/vmalloc.h>
# include <linux/fs.h>
# include <linux/string.h>
# include <linux/kernel.h>
#if 0
# define DEBUGP printk
# else
# define DEBUGP(fmt...)
# endif
2011-03-22 13:39:27 +10:00
# ifdef CONFIG_MODULES
2005-04-16 15:20:36 -07:00
void * module_alloc ( unsigned long size )
{
if ( size = = 0 )
return NULL ;
return vmalloc ( size ) ;
}
/* Free memory returned from module_alloc */
void module_free ( struct module * mod , void * module_region )
{
vfree ( module_region ) ;
}
/* We don't need anything special. */
int module_frob_arch_sections ( Elf_Ehdr * hdr ,
Elf_Shdr * sechdrs ,
char * secstrings ,
struct module * mod )
{
return 0 ;
}
int apply_relocate ( Elf32_Shdr * sechdrs ,
const char * strtab ,
unsigned int symindex ,
unsigned int relsec ,
struct module * me )
{
unsigned int i ;
Elf32_Rel * rel = ( void * ) sechdrs [ relsec ] . sh_addr ;
Elf32_Sym * sym ;
uint32_t * location ;
DEBUGP ( " Applying relocate section %u to %u \n " , relsec ,
sechdrs [ relsec ] . sh_info ) ;
for ( i = 0 ; i < sechdrs [ relsec ] . sh_size / sizeof ( * rel ) ; i + + ) {
/* This is where to make the change */
location = ( void * ) sechdrs [ sechdrs [ relsec ] . sh_info ] . sh_addr
+ rel [ i ] . r_offset ;
/* This is the symbol it is referring to. Note that all
undefined symbols have been resolved . */
sym = ( Elf32_Sym * ) sechdrs [ symindex ] . sh_addr
+ ELF32_R_SYM ( rel [ i ] . r_info ) ;
switch ( ELF32_R_TYPE ( rel [ i ] . r_info ) ) {
case R_68K_32 :
/* We add the value into the location given */
* location + = sym - > st_value ;
break ;
case R_68K_PC32 :
/* Add the value, subtract its postition */
* location + = sym - > st_value - ( uint32_t ) location ;
break ;
default :
printk ( KERN_ERR " module %s: Unknown relocation: %u \n " ,
me - > name , ELF32_R_TYPE ( rel [ i ] . r_info ) ) ;
return - ENOEXEC ;
}
}
return 0 ;
}
int apply_relocate_add ( Elf32_Shdr * sechdrs ,
const char * strtab ,
unsigned int symindex ,
unsigned int relsec ,
struct module * me )
{
unsigned int i ;
Elf32_Rela * rel = ( void * ) sechdrs [ relsec ] . sh_addr ;
Elf32_Sym * sym ;
uint32_t * location ;
DEBUGP ( " Applying relocate_add section %u to %u \n " , relsec ,
sechdrs [ relsec ] . sh_info ) ;
for ( i = 0 ; i < sechdrs [ relsec ] . sh_size / sizeof ( * rel ) ; i + + ) {
/* This is where to make the change */
location = ( void * ) sechdrs [ sechdrs [ relsec ] . sh_info ] . sh_addr
+ rel [ i ] . r_offset ;
/* This is the symbol it is referring to. Note that all
undefined symbols have been resolved . */
sym = ( Elf32_Sym * ) sechdrs [ symindex ] . sh_addr
+ ELF32_R_SYM ( rel [ i ] . r_info ) ;
switch ( ELF32_R_TYPE ( rel [ i ] . r_info ) ) {
case R_68K_32 :
/* We add the value into the location given */
* location = rel [ i ] . r_addend + sym - > st_value ;
break ;
case R_68K_PC32 :
/* Add the value, subtract its postition */
* location = rel [ i ] . r_addend + sym - > st_value - ( uint32_t ) location ;
break ;
default :
printk ( KERN_ERR " module %s: Unknown relocation: %u \n " ,
me - > name , ELF32_R_TYPE ( rel [ i ] . r_info ) ) ;
return - ENOEXEC ;
}
}
return 0 ;
}
int module_finalize ( const Elf_Ehdr * hdr ,
const Elf_Shdr * sechdrs ,
2011-03-22 13:39:27 +10:00
struct module * mod )
2005-04-16 15:20:36 -07:00
{
2011-03-22 13:39:27 +10:00
module_fixup ( mod , mod - > arch . fixup_start , mod - > arch . fixup_end ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
void module_arch_cleanup ( struct module * mod )
{
}
2011-03-22 13:39:27 +10:00
# endif /* CONFIG_MODULES */
void module_fixup ( struct module * mod , struct m68k_fixup_info * start ,
struct m68k_fixup_info * end )
{
struct m68k_fixup_info * fixup ;
for ( fixup = start ; fixup < end ; fixup + + ) {
switch ( fixup - > type ) {
case m68k_fixup_memoffset :
* ( u32 * ) fixup - > addr = m68k_memoffset ;
break ;
case m68k_fixup_vnode_shift :
* ( u16 * ) fixup - > addr + = m68k_virt_to_node_shift ;
break ;
}
}
}