Copied from armv7/start.S. Tested on an ARM1176JZF-S SoC.

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

diff --git a/arch/arm/cpu/arm1176/start.S b/arch/arm/cpu/arm1176/start.S
index d3ab5928eee..7bdcb5fb97b 100644
--- a/arch/arm/cpu/arm1176/start.S
+++ b/arch/arm/cpu/arm1176/start.S
@@ -37,6 +37,41 @@ reset:
        b       save_boot_params
 .globl save_boot_params_ret
 save_boot_params_ret:
+#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
@@ -115,3 +150,10 @@ c_runtime_cpu_setup:
 WEAK(save_boot_params)
        b       save_boot_params_ret    /* back to my caller */
 ENDPROC(save_boot_params)
+
+#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