]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
3da0e575 AA |
2 | /* |
3 | * relocate - common relocation function for ARM U-Boot | |
4 | * | |
5 | * Copyright (c) 2013 Albert ARIBAUD <[email protected]> | |
3da0e575 AA |
6 | */ |
7 | ||
3ff46cc4 | 8 | #include <asm-offsets.h> |
d22336aa | 9 | #include <asm/assembler.h> |
3ff46cc4 | 10 | #include <config.h> |
c70f74a0 | 11 | #include <elf.h> |
3da0e575 | 12 | #include <linux/linkage.h> |
12d8a729 | 13 | #ifdef CONFIG_CPU_V7M |
14 | #include <asm/armv7m.h> | |
15 | #endif | |
3da0e575 | 16 | |
db544b96 AA |
17 | /* |
18 | * Default/weak exception vectors relocation routine | |
19 | * | |
20 | * This routine covers the standard ARM cases: normal (0x00000000), | |
21 | * high (0xffff0000) and VBAR. SoCs which do not comply with any of | |
22 | * the standard cases must provide their own, strong, version. | |
23 | */ | |
24 | ||
25 | .section .text.relocate_vectors,"ax",%progbits | |
db544b96 | 26 | |
fc224004 | 27 | WEAK(relocate_vectors) |
db544b96 | 28 | |
12d8a729 | 29 | #ifdef CONFIG_CPU_V7M |
30 | /* | |
31 | * On ARMv7-M we only have to write the new vector address | |
32 | * to VTOR register. | |
33 | */ | |
34 | ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ | |
35 | ldr r1, =V7M_SCB_BASE | |
36 | str r0, [r1, V7M_SCB_VTOR] | |
37 | #else | |
db544b96 AA |
38 | #ifdef CONFIG_HAS_VBAR |
39 | /* | |
40 | * If the ARM processor has the security extensions, | |
41 | * use VBAR to relocate the exception vectors. | |
42 | */ | |
43 | ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ | |
44 | mcr p15, 0, r0, c12, c0, 0 /* Set VBAR */ | |
45 | #else | |
46 | /* | |
47 | * Copy the relocated exception vectors to the | |
48 | * correct address | |
49 | * CP15 c1 V bit gives us the location of the vectors: | |
50 | * 0x00000000 or 0xFFFF0000. | |
51 | */ | |
52 | ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ | |
53 | mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */ | |
54 | ands r2, r2, #(1 << 13) | |
55 | ldreq r1, =0x00000000 /* If V=0 */ | |
56 | ldrne r1, =0xFFFF0000 /* If V=1 */ | |
57 | ldmia r0!, {r2-r8,r10} | |
58 | stmia r1!, {r2-r8,r10} | |
59 | ldmia r0!, {r2-r8,r10} | |
60 | stmia r1!, {r2-r8,r10} | |
12d8a729 | 61 | #endif |
db544b96 | 62 | #endif |
583f1b2f | 63 | ret lr |
db544b96 AA |
64 | |
65 | ENDPROC(relocate_vectors) | |
66 | ||
3da0e575 AA |
67 | /* |
68 | * void relocate_code(addr_moni) | |
69 | * | |
70 | * This function relocates the monitor code. | |
71 | * | |
72 | * NOTE: | |
73 | * To prevent the code below from containing references with an R_ARM_ABS32 | |
74 | * relocation record type, we never refer to linker-defined symbols directly. | |
75 | * Instead, we declare literals which contain their relative location with | |
76 | * respect to relocate_code, and at run time, add relocate_code back to them. | |
77 | */ | |
78 | ||
79 | ENTRY(relocate_code) | |
81e712a9 AP |
80 | relocate_base: |
81 | adr r3, relocate_base | |
cd82f199 CWW |
82 | ldr r1, _image_copy_start_ofs |
83 | add r1, r3 /* r1 <- Run &__image_copy_start */ | |
84 | subs r4, r0, r1 /* r4 <- Run to copy offset */ | |
85 | beq relocate_done /* skip relocation */ | |
86 | ldr r1, _image_copy_start_ofs | |
87 | add r1, r3 /* r1 <- Run &__image_copy_start */ | |
88 | ldr r2, _image_copy_end_ofs | |
89 | add r2, r3 /* r2 <- Run &__image_copy_end */ | |
3da0e575 | 90 | copy_loop: |
cd82f199 CWW |
91 | ldmia r1!, {r10-r11} /* copy from source address [r1] */ |
92 | stmia r0!, {r10-r11} /* copy to target address [r0] */ | |
93 | cmp r1, r2 /* until source end address [r2] */ | |
3da0e575 AA |
94 | blo copy_loop |
95 | ||
96 | /* | |
97 | * fix .rel.dyn relocations | |
98 | */ | |
cd82f199 CWW |
99 | ldr r1, _rel_dyn_start_ofs |
100 | add r2, r1, r3 /* r2 <- Run &__rel_dyn_start */ | |
101 | ldr r1, _rel_dyn_end_ofs | |
102 | add r3, r1, r3 /* r3 <- Run &__rel_dyn_end */ | |
3da0e575 | 103 | fixloop: |
fbf87b18 AA |
104 | ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ |
105 | and r1, r1, #0xff | |
c70f74a0 | 106 | cmp r1, #R_ARM_RELATIVE |
fbf87b18 AA |
107 | bne fixnext |
108 | ||
3da0e575 | 109 | /* relative fix: increase location by offset */ |
a81872ff | 110 | add r0, r0, r4 |
3da0e575 | 111 | ldr r1, [r0] |
a81872ff | 112 | add r1, r1, r4 |
3da0e575 | 113 | str r1, [r0] |
fbf87b18 | 114 | fixnext: |
3da0e575 AA |
115 | cmp r2, r3 |
116 | blo fixloop | |
117 | ||
118 | relocate_done: | |
119 | ||
9dc8fef2 MD |
120 | #ifdef __XSCALE__ |
121 | /* | |
122 | * On xscale, icache must be invalidated and write buffers drained, | |
123 | * even with cache disabled - 4.2.7 of xscale core developer's manual | |
124 | */ | |
125 | mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */ | |
126 | mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ | |
127 | #endif | |
128 | ||
583f1b2f | 129 | ret lr |
3da0e575 | 130 | |
3da0e575 | 131 | ENDPROC(relocate_code) |
cd82f199 CWW |
132 | |
133 | _image_copy_start_ofs: | |
134 | .word __image_copy_start - relocate_code | |
135 | _image_copy_end_ofs: | |
136 | .word __image_copy_end - relocate_code | |
137 | _rel_dyn_start_ofs: | |
138 | .word __rel_dyn_start - relocate_code | |
139 | _rel_dyn_end_ofs: | |
140 | .word __rel_dyn_end - relocate_code |