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)