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