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