13da0e575SAlbert ARIBAUD/* 23da0e575SAlbert ARIBAUD * relocate - common relocation function for ARM U-Boot 33da0e575SAlbert ARIBAUD * 43da0e575SAlbert ARIBAUD * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> 53da0e575SAlbert ARIBAUD * 63da0e575SAlbert ARIBAUD * See file CREDITS for list of people who contributed to this 73da0e575SAlbert ARIBAUD * project. 83da0e575SAlbert ARIBAUD * 93da0e575SAlbert ARIBAUD * This program is free software; you can redistribute it and/or 103da0e575SAlbert ARIBAUD * modify it under the terms of the GNU General Public License as 113da0e575SAlbert ARIBAUD * published by the Free Software Foundation; either version 2 of 123da0e575SAlbert ARIBAUD * the License, or (at your option) any later version. 133da0e575SAlbert ARIBAUD * 143da0e575SAlbert ARIBAUD * This program is distributed in the hope that it will be useful, 153da0e575SAlbert ARIBAUD * but WITHOUT ANY WARRANTY; without even the implied warranty of 163da0e575SAlbert ARIBAUD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 173da0e575SAlbert ARIBAUD * GNU General Public License for more details. 183da0e575SAlbert ARIBAUD * 193da0e575SAlbert ARIBAUD * You should have received a copy of the GNU General Public License 203da0e575SAlbert ARIBAUD * along with this program; if not, write to the Free Software 213da0e575SAlbert ARIBAUD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 223da0e575SAlbert ARIBAUD * MA 02111-1307 USA 233da0e575SAlbert ARIBAUD */ 243da0e575SAlbert ARIBAUD 253da0e575SAlbert ARIBAUD#include <linux/linkage.h> 263da0e575SAlbert ARIBAUD 273da0e575SAlbert ARIBAUD/* 283da0e575SAlbert ARIBAUD * void relocate_code(addr_moni) 293da0e575SAlbert ARIBAUD * 303da0e575SAlbert ARIBAUD * This function relocates the monitor code. 313da0e575SAlbert ARIBAUD * 323da0e575SAlbert ARIBAUD * NOTE: 333da0e575SAlbert ARIBAUD * To prevent the code below from containing references with an R_ARM_ABS32 343da0e575SAlbert ARIBAUD * relocation record type, we never refer to linker-defined symbols directly. 353da0e575SAlbert ARIBAUD * Instead, we declare literals which contain their relative location with 363da0e575SAlbert ARIBAUD * respect to relocate_code, and at run time, add relocate_code back to them. 373da0e575SAlbert ARIBAUD */ 383da0e575SAlbert ARIBAUD 393da0e575SAlbert ARIBAUDENTRY(relocate_code) 403da0e575SAlbert ARIBAUD mov r6, r0 /* save addr of destination */ 413da0e575SAlbert ARIBAUD 42d026dec8SAlbert ARIBAUD ldr r0, =__image_copy_start /* r0 <- SRC &__image_copy_start */ 433da0e575SAlbert ARIBAUD subs r9, r6, r0 /* r9 <- relocation offset */ 443da0e575SAlbert ARIBAUD beq relocate_done /* skip relocation */ 453da0e575SAlbert ARIBAUD mov r1, r6 /* r1 <- scratch for copy loop */ 463da0e575SAlbert ARIBAUD adr r7, relocate_code /* r7 <- SRC &relocate_code */ 47d026dec8SAlbert ARIBAUD ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ 483da0e575SAlbert ARIBAUD 493da0e575SAlbert ARIBAUDcopy_loop: 503da0e575SAlbert ARIBAUD ldmia r0!, {r10-r11} /* copy from source address [r0] */ 513da0e575SAlbert ARIBAUD stmia r1!, {r10-r11} /* copy to target address [r1] */ 523da0e575SAlbert ARIBAUD cmp r0, r2 /* until source end address [r2] */ 533da0e575SAlbert ARIBAUD blo copy_loop 543da0e575SAlbert ARIBAUD 553da0e575SAlbert ARIBAUD /* 563da0e575SAlbert ARIBAUD * fix .rel.dyn relocations 573da0e575SAlbert ARIBAUD */ 58*47bd65efSAlbert ARIBAUD ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ 59*47bd65efSAlbert ARIBAUD ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ 603da0e575SAlbert ARIBAUDfixloop: 613da0e575SAlbert ARIBAUD ldr r0, [r2] /* r0 <- SRC location to fix up */ 623da0e575SAlbert ARIBAUD add r0, r0, r9 /* r0 <- DST location to fix up */ 633da0e575SAlbert ARIBAUD ldr r1, [r2, #4] 643da0e575SAlbert ARIBAUD and r7, r1, #0xff 653da0e575SAlbert ARIBAUD cmp r7, #23 /* relative fixup? */ 663da0e575SAlbert ARIBAUD beq fixrel 673da0e575SAlbert ARIBAUD /* ignore unknown type of fixup */ 683da0e575SAlbert ARIBAUD b fixnext 693da0e575SAlbert ARIBAUDfixrel: 703da0e575SAlbert ARIBAUD /* relative fix: increase location by offset */ 713da0e575SAlbert ARIBAUD ldr r1, [r0] 723da0e575SAlbert ARIBAUD add r1, r1, r9 733da0e575SAlbert ARIBAUDfixnext: 743da0e575SAlbert ARIBAUD str r1, [r0] 753da0e575SAlbert ARIBAUD add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ 763da0e575SAlbert ARIBAUD cmp r2, r3 773da0e575SAlbert ARIBAUD blo fixloop 783da0e575SAlbert ARIBAUD 793da0e575SAlbert ARIBAUDrelocate_done: 803da0e575SAlbert ARIBAUD 813da0e575SAlbert ARIBAUD /* ARMv4- don't know bx lr but the assembler fails to see that */ 823da0e575SAlbert ARIBAUD 833da0e575SAlbert ARIBAUD#ifdef __ARM_ARCH_4__ 843da0e575SAlbert ARIBAUD mov pc, lr 853da0e575SAlbert ARIBAUD#else 863da0e575SAlbert ARIBAUD bx lr 873da0e575SAlbert ARIBAUD#endif 883da0e575SAlbert ARIBAUD 893da0e575SAlbert ARIBAUDENDPROC(relocate_code) 90