]>
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> | |
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 | ||
15 | unsigned 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) { | |
1f83b8f1 MF |
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; | |
1394f032 | 32 | |
1f83b8f1 MF |
33 | case FLAT_BFIN_RELOC_TYPE_32_BIT: |
34 | pr_debug("*ptr = %lx", get_unaligned(ptr)); | |
35 | val = get_unaligned(ptr); | |
36 | break; | |
1394f032 | 37 | |
1f83b8f1 MF |
38 | default: |
39 | pr_debug("BINFMT_FLAT: Unknown relocation type %x\n", type); | |
40 | return 0; | |
1394f032 BW |
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 | } | |
55 | EXPORT_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 | */ | |
61 | void 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) { | |
1f83b8f1 MF |
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; | |
1394f032 | 72 | |
1f83b8f1 MF |
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; | |
1394f032 | 77 | |
1f83b8f1 MF |
78 | case FLAT_BFIN_RELOC_TYPE_32_BIT: |
79 | put_unaligned(addr, ptr); | |
80 | pr_debug("new ptr =%lx", get_unaligned(ptr)); | |
81 | break; | |
1394f032 BW |
82 | } |
83 | } | |
84 | EXPORT_SYMBOL(bfin_put_addr_at_rp); |