1/* 2 * Copyright 2007 Analog Devices Inc. 3 * 4 * Licensed under the GPL-2. 5 */ 6 7#include <linux/module.h> 8#include <linux/sched.h> 9#include <linux/flat.h> 10 11#define FLAT_BFIN_RELOC_TYPE_16_BIT 0 12#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1 13#define FLAT_BFIN_RELOC_TYPE_32_BIT 2 14 15unsigned long bfin_get_addr_from_rp(unsigned long *ptr, 16 unsigned long relval, 17 unsigned long flags, 18 unsigned long *persistent) 19{ 20 unsigned short *usptr = (unsigned short *)ptr; 21 int type = (relval >> 26) & 7; 22 unsigned long val; 23 24 switch (type) { 25 case FLAT_BFIN_RELOC_TYPE_16_BIT: 26 case FLAT_BFIN_RELOC_TYPE_16H_BIT: 27 usptr = (unsigned short *)ptr; 28 pr_debug("*usptr = %x", get_unaligned(usptr)); 29 val = get_unaligned(usptr); 30 val += *persistent; 31 break; 32 33 case FLAT_BFIN_RELOC_TYPE_32_BIT: 34 pr_debug("*ptr = %lx", get_unaligned(ptr)); 35 val = get_unaligned(ptr); 36 break; 37 38 default: 39 pr_debug("BINFMT_FLAT: Unknown relocation type %x\n", type); 40 return 0; 41 } 42 43 /* 44 * Stack-relative relocs contain the offset into the stack, we 45 * have to add the stack's start address here and return 1 from 46 * flat_addr_absolute to prevent the normal address calculations 47 */ 48 if (relval & (1 << 29)) 49 return val + current->mm->context.end_brk; 50 51 if ((flags & FLAT_FLAG_GOTPIC) == 0) 52 val = htonl(val); 53 return val; 54} 55EXPORT_SYMBOL(bfin_get_addr_from_rp); 56 57/* 58 * Insert the address ADDR into the symbol reference at RP; 59 * RELVAL is the raw relocation-table entry from which RP is derived 60 */ 61void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr, 62 unsigned long relval) 63{ 64 unsigned short *usptr = (unsigned short *)ptr; 65 int type = (relval >> 26) & 7; 66 67 switch (type) { 68 case FLAT_BFIN_RELOC_TYPE_16_BIT: 69 put_unaligned(addr, usptr); 70 pr_debug("new value %x at %p", get_unaligned(usptr), usptr); 71 break; 72 73 case FLAT_BFIN_RELOC_TYPE_16H_BIT: 74 put_unaligned(addr >> 16, usptr); 75 pr_debug("new value %x", get_unaligned(usptr)); 76 break; 77 78 case FLAT_BFIN_RELOC_TYPE_32_BIT: 79 put_unaligned(addr, ptr); 80 pr_debug("new ptr =%lx", get_unaligned(ptr)); 81 break; 82 } 83} 84EXPORT_SYMBOL(bfin_put_addr_at_rp); 85