ubuntu-phone team mailing list archive
-
ubuntu-phone team
-
Mailing list archive
-
Message #00294
[PATCH 1/2] [PATCH] UBUNTU: Support copying of atags in the decompressor.
OriginalAuthor: Mike Kasick <mike@xxxxxxxxxx>
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 <jens.andersen@xxxxxxxxx>'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 <vbocek@xxxxxxxxx>
---
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
References