183d290c5STom Rini/* SPDX-License-Identifier: GPL-2.0+ */ 23da0e575SAlbert ARIBAUD/* 33da0e575SAlbert ARIBAUD * relocate - common relocation function for ARM U-Boot 43da0e575SAlbert ARIBAUD * 53da0e575SAlbert ARIBAUD * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> 63da0e575SAlbert ARIBAUD */ 73da0e575SAlbert ARIBAUD 83ff46cc4SGeorges Savoundararadj#include <asm-offsets.h> 9d22336aaSVikas Manocha#include <asm/assembler.h> 103ff46cc4SGeorges Savoundararadj#include <config.h> 11c70f74a0SSimon Glass#include <elf.h> 123da0e575SAlbert ARIBAUD#include <linux/linkage.h> 1312d8a729Srev13@wp.pl#ifdef CONFIG_CPU_V7M 1412d8a729Srev13@wp.pl#include <asm/armv7m.h> 1512d8a729Srev13@wp.pl#endif 163da0e575SAlbert ARIBAUD 173da0e575SAlbert ARIBAUD/* 18db544b96SAlbert ARIBAUD * Default/weak exception vectors relocation routine 19db544b96SAlbert ARIBAUD * 20db544b96SAlbert ARIBAUD * This routine covers the standard ARM cases: normal (0x00000000), 21db544b96SAlbert ARIBAUD * high (0xffff0000) and VBAR. SoCs which do not comply with any of 22db544b96SAlbert ARIBAUD * the standard cases must provide their own, strong, version. 23db544b96SAlbert ARIBAUD */ 24db544b96SAlbert ARIBAUD 25db544b96SAlbert ARIBAUD .section .text.relocate_vectors,"ax",%progbits 26db544b96SAlbert ARIBAUD .weak relocate_vectors 27db544b96SAlbert ARIBAUD 28db544b96SAlbert ARIBAUDENTRY(relocate_vectors) 29db544b96SAlbert ARIBAUD 3012d8a729Srev13@wp.pl#ifdef CONFIG_CPU_V7M 3112d8a729Srev13@wp.pl /* 3212d8a729Srev13@wp.pl * On ARMv7-M we only have to write the new vector address 3312d8a729Srev13@wp.pl * to VTOR register. 3412d8a729Srev13@wp.pl */ 3512d8a729Srev13@wp.pl ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 3612d8a729Srev13@wp.pl ldr r1, =V7M_SCB_BASE 3712d8a729Srev13@wp.pl str r0, [r1, V7M_SCB_VTOR] 3812d8a729Srev13@wp.pl#else 39db544b96SAlbert ARIBAUD#ifdef CONFIG_HAS_VBAR 40db544b96SAlbert ARIBAUD /* 41db544b96SAlbert ARIBAUD * If the ARM processor has the security extensions, 42db544b96SAlbert ARIBAUD * use VBAR to relocate the exception vectors. 43db544b96SAlbert ARIBAUD */ 44db544b96SAlbert ARIBAUD ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 45db544b96SAlbert ARIBAUD mcr p15, 0, r0, c12, c0, 0 /* Set VBAR */ 46db544b96SAlbert ARIBAUD#else 47db544b96SAlbert ARIBAUD /* 48db544b96SAlbert ARIBAUD * Copy the relocated exception vectors to the 49db544b96SAlbert ARIBAUD * correct address 50db544b96SAlbert ARIBAUD * CP15 c1 V bit gives us the location of the vectors: 51db544b96SAlbert ARIBAUD * 0x00000000 or 0xFFFF0000. 52db544b96SAlbert ARIBAUD */ 53db544b96SAlbert ARIBAUD ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 54db544b96SAlbert ARIBAUD mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */ 55db544b96SAlbert ARIBAUD ands r2, r2, #(1 << 13) 56db544b96SAlbert ARIBAUD ldreq r1, =0x00000000 /* If V=0 */ 57db544b96SAlbert ARIBAUD ldrne r1, =0xFFFF0000 /* If V=1 */ 58db544b96SAlbert ARIBAUD ldmia r0!, {r2-r8,r10} 59db544b96SAlbert ARIBAUD stmia r1!, {r2-r8,r10} 60db544b96SAlbert ARIBAUD ldmia r0!, {r2-r8,r10} 61db544b96SAlbert ARIBAUD stmia r1!, {r2-r8,r10} 62db544b96SAlbert ARIBAUD#endif 6312d8a729Srev13@wp.pl#endif 64db544b96SAlbert ARIBAUD bx lr 65db544b96SAlbert ARIBAUD 66db544b96SAlbert ARIBAUDENDPROC(relocate_vectors) 67db544b96SAlbert ARIBAUD 68db544b96SAlbert ARIBAUD/* 693da0e575SAlbert ARIBAUD * void relocate_code(addr_moni) 703da0e575SAlbert ARIBAUD * 713da0e575SAlbert ARIBAUD * This function relocates the monitor code. 723da0e575SAlbert ARIBAUD * 733da0e575SAlbert ARIBAUD * NOTE: 743da0e575SAlbert ARIBAUD * To prevent the code below from containing references with an R_ARM_ABS32 753da0e575SAlbert ARIBAUD * relocation record type, we never refer to linker-defined symbols directly. 763da0e575SAlbert ARIBAUD * Instead, we declare literals which contain their relative location with 773da0e575SAlbert ARIBAUD * respect to relocate_code, and at run time, add relocate_code back to them. 783da0e575SAlbert ARIBAUD */ 793da0e575SAlbert ARIBAUD 803da0e575SAlbert ARIBAUDENTRY(relocate_code) 81*86c21f0aSChia-Wei, Wang adr r3, relocate_code 82*86c21f0aSChia-Wei, Wang ldr r1, _image_copy_start_ofs 83*86c21f0aSChia-Wei, Wang add r1, r3 /* r1 <- Run &__image_copy_start */ 84*86c21f0aSChia-Wei, Wang subs r4, r0, r1 /* r4 <- Run to copy offset */ 853da0e575SAlbert ARIBAUD beq relocate_done /* skip relocation */ 86*86c21f0aSChia-Wei, Wang ldr r1, _image_copy_start_ofs 87*86c21f0aSChia-Wei, Wang add r1, r3 /* r1 <- Run &__image_copy_start */ 88*86c21f0aSChia-Wei, Wang ldr r2, _image_copy_end_ofs 89*86c21f0aSChia-Wei, Wang add r2, r3 /* r2 <- Run &__image_copy_end */ 903da0e575SAlbert ARIBAUDcopy_loop: 91fbf87b18SAlbert ARIBAUD ldmia r1!, {r10-r11} /* copy from source address [r1] */ 92fbf87b18SAlbert ARIBAUD stmia r0!, {r10-r11} /* copy to target address [r0] */ 93fbf87b18SAlbert ARIBAUD cmp r1, r2 /* until source end address [r2] */ 943da0e575SAlbert ARIBAUD blo copy_loop 953da0e575SAlbert ARIBAUD 963da0e575SAlbert ARIBAUD /* 973da0e575SAlbert ARIBAUD * fix .rel.dyn relocations 983da0e575SAlbert ARIBAUD */ 99*86c21f0aSChia-Wei, Wang ldr r1, _rel_dyn_start_ofs 100*86c21f0aSChia-Wei, Wang add r2, r1, r3 /* r2 <- Run &__rel_dyn_start */ 101*86c21f0aSChia-Wei, Wang ldr r1, _rel_dyn_end_ofs 102*86c21f0aSChia-Wei, Wang add r3, r1, r3 /* r3 <- Run &__rel_dyn_end */ 1033da0e575SAlbert ARIBAUDfixloop: 104fbf87b18SAlbert ARIBAUD ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ 105fbf87b18SAlbert ARIBAUD and r1, r1, #0xff 106c70f74a0SSimon Glass cmp r1, #R_ARM_RELATIVE 107fbf87b18SAlbert ARIBAUD bne fixnext 108fbf87b18SAlbert ARIBAUD 1093da0e575SAlbert ARIBAUD /* relative fix: increase location by offset */ 110a81872ffSJeroen Hofstee add r0, r0, r4 1113da0e575SAlbert ARIBAUD ldr r1, [r0] 112a81872ffSJeroen Hofstee add r1, r1, r4 1133da0e575SAlbert ARIBAUD str r1, [r0] 114fbf87b18SAlbert ARIBAUDfixnext: 1153da0e575SAlbert ARIBAUD cmp r2, r3 1163da0e575SAlbert ARIBAUD blo fixloop 1173da0e575SAlbert ARIBAUD 1183da0e575SAlbert ARIBAUDrelocate_done: 1193da0e575SAlbert ARIBAUD 1209dc8fef2SMike Dunn#ifdef __XSCALE__ 1219dc8fef2SMike Dunn /* 1229dc8fef2SMike Dunn * On xscale, icache must be invalidated and write buffers drained, 1239dc8fef2SMike Dunn * even with cache disabled - 4.2.7 of xscale core developer's manual 1249dc8fef2SMike Dunn */ 1259dc8fef2SMike Dunn mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */ 1269dc8fef2SMike Dunn mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 1279dc8fef2SMike Dunn#endif 1289dc8fef2SMike Dunn 1293da0e575SAlbert ARIBAUD /* ARMv4- don't know bx lr but the assembler fails to see that */ 1303da0e575SAlbert ARIBAUD 1313da0e575SAlbert ARIBAUD#ifdef __ARM_ARCH_4__ 1323da0e575SAlbert ARIBAUD mov pc, lr 1333da0e575SAlbert ARIBAUD#else 1343da0e575SAlbert ARIBAUD bx lr 1353da0e575SAlbert ARIBAUD#endif 1363da0e575SAlbert ARIBAUD 1373da0e575SAlbert ARIBAUDENDPROC(relocate_code) 138*86c21f0aSChia-Wei, Wang 139*86c21f0aSChia-Wei, Wang_image_copy_start_ofs: 140*86c21f0aSChia-Wei, Wang .word __image_copy_start - relocate_code 141*86c21f0aSChia-Wei, Wang_image_copy_end_ofs: 142*86c21f0aSChia-Wei, Wang .word __image_copy_end - relocate_code 143*86c21f0aSChia-Wei, Wang_rel_dyn_start_ofs: 144*86c21f0aSChia-Wei, Wang .word __rel_dyn_start - relocate_code 145*86c21f0aSChia-Wei, Wang_rel_dyn_end_ofs: 146*86c21f0aSChia-Wei, Wang .word __rel_dyn_end - relocate_code 147