summaryrefslogtreecommitdiff
path: root/arch/arm/boot/compressed/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/boot/compressed/head.S')
-rw-r--r--arch/arm/boot/compressed/head.S53
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index c5191b1532e8..437943d6b55e 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -120,6 +120,16 @@ wait: mrc p14, 0, pc, c0, c1, 0
#endif
.endm
+ .macro debug_passed_physoffset
+#ifdef DEBUG
+ bleq 1f
+ kputc #'!'
+ kphex r9, 8
+ kputc #'\n'
+1:
+#endif
+ .endm
+
.section ".start", #alloc, #execinstr
/*
* sort out different calling conventions
@@ -137,6 +147,7 @@ start:
.word _edata @ zImage end address
1: mov r7, r1 @ save architecture ID
mov r8, r2 @ save atags pointer
+ mov r9, r3 @ save phys_offset
#ifndef __ARM_ARCH_2__
/*
@@ -234,6 +245,47 @@ not_relocated: mov r0, #0
cmp r2, r3
blo 1b
+#ifdef CONFIG_RUNTIME_PHYS_OFFSET
+ /*
+ * assert physoffset passed by bootloader is properly
+ * 2MiB-aligned, ...
+ */
+ ldr r10, =0x001fffff
+
+ tst r9, r10
+ debug_passed_physoffset
+ tst r9, r10
+
+ /*
+ * ... if not guess it based on sp.
+ * sp & 0xf8000000 should work for most machines. The needed
+ * preconditions are:
+ * - physoffset is aligned to a 128MiB boundary
+ * (As of Jan 2010 all but s3c2400, u300 and at91 have it.
+ * For the latter it depends on configuration.)
+ * - sp < physoffset + 128MiB (which is definitely true if you
+ * only have 128MiB of RAM or less)
+ */
+#ifdef CONFIG_ARCH_MX5
+ and r9, sp, #0xf8000000
+#else
+ andne r9, sp, #0xf8000000
+#endif
+#ifdef DEBUG
+ kputc #'P'
+ kphex r9, 8
+ kputc #'\n'
+#endif
+
+ add r4, r9, #TEXT_OFFSET
+#else /* ifdef CONFIG_RUNTIME_PHYS_OFFSET */
+ /* warn on r4(ZRELADDR) != r9 + TEXT_OFFSET */
+ add r10, r9, #TEXT_OFFSET
+ cmp r10, r4
+ debug_passed_physoffset
+
+#endif /* ifdef CONFIG_RUNTIME_PHYS_OFFSET / else */
+
/*
* The C runtime environment should now be setup
* sufficiently. Turn the cache on, set up some
@@ -568,6 +620,7 @@ call_kernel: bl cache_clean_flush
mov r0, #0 @ must be zero
mov r1, r7 @ restore architecture number
mov r2, r8 @ restore atags pointer
+ sub r3, r4, #TEXT_OFFSET @ physoffset
mov pc, r4 @ call kernel
/*