summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv8/start.S
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2017-11-02 18:11:27 -0600
committerTom Rini <trini@konsulko.com>2017-11-17 07:44:13 -0500
commit49e93875a62fb9e96a4a7483b9bd5d8ae27ea76e (patch)
tree8daa16b3ccae7e5fa772f32e9b2f0b76d532f17e /arch/arm/cpu/armv8/start.S
parent9679d339ad2d4c495d734bad3a0fb7be6c4215eb (diff)
arm64: support running at addr other than linked to
This is required in the case where U-Boot is typically loaded and run at a particular address, but for some reason the RAM at that location is not available, e.g. due to memory fragmentation loading other boot binaries or firmware, splitting an SMP complex between various different OSs without using e.g. the EL2 second-stage page tables to hide the memory asignments, or due to known ECC failures. Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/cpu/armv8/start.S')
-rw-r--r--arch/arm/cpu/armv8/start.S26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index 5c500be51d1..03e744e4a67 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -57,6 +57,32 @@ reset:
.globl save_boot_params_ret
save_boot_params_ret:
+#if CONFIG_POSITION_INDEPENDENT
+ /*
+ * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
+ * executed at a different address than it was linked at.
+ */
+pie_fixup:
+ adr x0, _start /* x0 <- Runtime value of _start */
+ ldr x1, _TEXT_BASE /* x1 <- Linked value of _start */
+ sub x9, x0, x1 /* x9 <- Run-vs-link offset */
+ adr x2, __rel_dyn_start /* x2 <- Runtime &__rel_dyn_start */
+ adr x3, __rel_dyn_end /* x3 <- Runtime &__rel_dyn_end */
+pie_fix_loop:
+ ldp x0, x1, [x2], #16 /* (x0, x1) <- (Link location, fixup) */
+ ldr x4, [x2], #8 /* x4 <- addend */
+ cmp w1, #1027 /* relative fixup? */
+ bne pie_skip_reloc
+ /* relative fix: store addend plus offset at dest location */
+ add x0, x0, x9
+ add x4, x4, x9
+ str x4, [x0]
+pie_skip_reloc:
+ cmp x2, x3
+ b.lo pie_fix_loop
+pie_fixup_done:
+#endif
+
#ifdef CONFIG_SYS_RESET_SCTRL
bl reset_sctrl
#endif