Copied from armv7/start.S. Tested on an ARM940T SoC.

Signed-off-by: Vencislav Atanasov <[email protected]>
---
 arch/arm/cpu/arm920t/start.S | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/arm/cpu/arm920t/start.S b/arch/arm/cpu/arm920t/start.S
index e792e8e795e..3d1f210af05 100644
--- a/arch/arm/cpu/arm920t/start.S
+++ b/arch/arm/cpu/arm920t/start.S
@@ -26,6 +26,42 @@
        .globl  reset
 
 reset:
+#ifdef CONFIG_POSITION_INDEPENDENT
+       /*
+        * Fix .rela.dyn relocations. This allows U-Boot to loaded to and
+        * executed at a different address than it was linked at.
+        */
+pie_fixup:
+       adr     r0, reset       /* r0 <- Runtime value of reset label */
+       ldr     r1, =reset      /* r1 <- Linked value of reset label */
+       subs    r4, r0, r1      /* r4 <- Runtime-vs-link offset */
+       beq     pie_fixup_done
+
+       adr     r0, pie_fixup
+       ldr     r1, _rel_dyn_start_ofs
+       add     r2, r0, r1      /* r2 <- Runtime &__rel_dyn_start */
+       ldr     r1, _rel_dyn_end_ofs
+       add     r3, r0, r1      /* r3 <- Runtime &__rel_dyn_end */
+
+pie_fix_loop:
+       ldr     r0, [r2]        /* r0 <- Link location */
+       ldr     r1, [r2, #4]    /* r1 <- fixup */
+       cmp     r1, #23         /* relative fixup? */
+       bne     pie_skip_reloc
+
+       /* relative fix: increase location by offset */
+       add     r0, r4
+       ldr     r1, [r0]
+       add     r1, r4
+       str     r1, [r0]
+       str     r0, [r2]
+       add     r2, #8
+pie_skip_reloc:
+       cmp     r2, r3
+       blo     pie_fix_loop
+pie_fixup_done:
+#endif
+
        /*
         * set the cpu to SVC32 mode
         */
@@ -95,3 +131,10 @@ cpu_init_crit:
 #endif
        mov     pc, lr
 #endif /* CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) */
+
+#if CONFIG_POSITION_INDEPENDENT
+_rel_dyn_start_ofs:
+       .word   __rel_dyn_start - pie_fixup
+_rel_dyn_end_ofs:
+       .word   __rel_dyn_end - pie_fixup
+#endif

-- 
Git-157)

Reply via email to