OriginalAuthor: Mike Kasick <[email protected]>

This is needed if this kernel is booted using kexec-hardboot[1],
because atags need to be in direct-mapped region, usually
the first 16kB of RAM.

Ported from Jens Andersen <[email protected]>'s
kernel for Asus TF201 [2].

[1] Hardboot: http://forum.xda-developers.com/showthread.php?t=1266827
[2] Original repository: http://git.io/EXpn2A

Signed-off-by: Vojtech Bocek <[email protected]>
---
 arch/arm/boot/compressed/Makefile |    3 +++
 arch/arm/boot/compressed/head.S   |   44 ++++++++++++++++++++++++++++++++++++-
 arch/arm/boot/compressed/misc.c   |   22 +++++++++++++++++++
 3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/compressed/Makefile 
b/arch/arm/boot/compressed/Makefile
index 0c74a6f..7643b37 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -111,6 +111,9 @@ endif
 ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
 LDFLAGS_vmlinux += --be8
 endif
+ifneq ($(PARAMS_PHYS),)
+LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS)
+endif
 # ?
 LDFLAGS_vmlinux += -p
 # Report unresolved symbol references
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 24701d6..5773670 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -133,7 +133,9 @@ start:
                .word   _edata                  @ zImage end address
  THUMB(                .thumb                  )
 1:             mov     r7, r1                  @ save architecture ID
-               mov     r8, r2                  @ save atags pointer
+               teq     r0, #0                  @ Check for kexec_boot_atags.
+               movne   r8, r0                  @ Save kexec_boot_tags.
+               moveq   r8, r2                  @ save atags pointer
 
 #ifndef __ARM_ARCH_2__
                /*
@@ -348,6 +350,44 @@ not_relocated:     mov     r0, #0
                add     r2, sp, #0x10000        @ 64k max
                mov     r3, r7
                bl      decompress_kernel
+
+/* Copy the kernel tagged list (atags):
+ *
+ * The kernel requires atags to be located in a direct-mapped region,
+ * usually below the kernel in the first 16 kB of RAM.  If they're above
+ * (the start of) the kernel, they need to be copied to a suitable
+ * location, e.g., the machine-defined params_phys.
+ *
+ * The assumption is that the tags will only be "out of place" if the
+ * decompressor code is also, so copying is implemented only in the "won't
+ * overwrite" case (which should be fixed).  Still need to make sure that
+ * the copied tags don't overwrite either the kernel or decompressor code
+ * (or rather, the remainder of it since everything up to here has already
+ * been executed).
+ *
+ * r4: zreladdr (kernel start)
+ * r8: atags */
+
+               /* No need to copy atags if they're already below kernel */
+               cmp     r8, r4
+               blo     call_kernel
+
+               /* r1: min(zreladdr, pc) */
+               mov     r1, pc
+               cmp     r4, r1
+               movlo   r1, r4
+
+               /* Compute max space for atags, if max <= 0 don't copy. */
+               ldr     r0, =params_phys        @ dest
+               subs    r2, r1, r0              @ max = min(zreladdr, pc) - dest
+               bls     call_kernel
+
+               /* Copy atags to params_phys. */
+               mov     r1, r8                  @ src
+               bl      copy_atags
+               mov     r8, r0
+
+call_kernel:
                bl      cache_clean_flush
                bl      cache_off
                mov     r0, #0                  @ must be zero
@@ -356,6 +396,8 @@ not_relocated:      mov     r0, #0
  ARM(          mov     pc, r4  )               @ call kernel
  THUMB(                bx      r4      )               @ entry point is always 
ARM
 
+               .ltorg
+
                .align  2
                .type   LC0, #object
 LC0:           .word   LC0                     @ r1
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 832d372..c082769 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -25,6 +25,7 @@ unsigned int __machine_arch_type;
 #include <linux/stddef.h>      /* for NULL */
 #include <linux/linkage.h>
 #include <asm/string.h>
+#include <asm/setup.h>
 
 
 static void putstr(const char *ptr);
@@ -192,3 +193,24 @@ decompress_kernel(unsigned long output_start, unsigned 
long free_mem_ptr_p,
        else
                putstr(" done, booting the kernel.\n");
 }
+
+const struct tag *copy_atags(struct tag *dest, const struct tag *src, size_t 
max)
+{
+       struct tag *tag;
+       size_t      size;
+
+       /* Find the last tag (ATAG_NONE). */
+       for_each_tag(tag, (struct tag *)src)
+               continue;
+
+       /* Include the last tag in copy. */
+       size = (char *)tag - (char *)src + sizeof(struct tag_header);
+
+       /* If there's not enough room, just use original and hope it works. */
+       if (size > max)
+               return src;
+
+       memcpy(dest, src, size);
+
+       return dest;
+}
-- 
1.7.10.4


-- 
Mailing list: https://launchpad.net/~ubuntu-phone
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~ubuntu-phone
More help   : https://help.launchpad.net/ListHelp

Reply via email to