From: Domenico Andreoli <[email-masked]>

This is the machinery used to bring code & data from the kernel to the
decompressor. This is effectively a relocation and it's done by hand,
using objcopy, specific ELF sections and some care in handling pointers
and strings.

Signed-off-by: Domenico Andreoli <[email-masked]>

---
 arch/arm/boot/Makefile                  |   10 +++++++-
 arch/arm/boot/compressed/Makefile       |    2 +-
 arch/arm/boot/compressed/arch.c         |   38 ++++++++++++++++++++++++++++++++
 arch/arm/boot/compressed/arch.h         |   22 +++++++++++++++++++
 arch/arm/boot/compressed/vmlinux.lds.in |    9 ++++++++
 arch/arm/kernel/vmlinux.lds.S           |   16 +++++++++++++
 6 files changed, 95 insertions(+), 2 deletions(-)

Index: b/arch/arm/boot/Makefile
===================================================================
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -48,7 +48,15 @@ $(obj)/Image: vmlinux FORCE
 	$(call if_changed,objcopy)
 	@echo '  Kernel: $@ is ready'
 
-$(obj)/compressed/vmlinux: $(obj)/Image FORCE
+OBJCOPYFLAGS_arch_reloc.o = -O elf32-littlearm \
+	-j .text.decomp \
+	-j .init.decomp.data \
+	-j .init.decomp.tags \
+	-j .ARM.attributes
+$(obj)/compressed/arch_reloc.o: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/compressed/vmlinux: $(obj)/Image $(obj)/compressed/arch_reloc.o FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage:	$(obj)/compressed/vmlinux FORCE
Index: b/arch/arm/boot/compressed/Makefile
===================================================================
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -23,7 +23,7 @@ endif
 
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
 HEAD	= head.o
-OBJS	+= misc.o decompress.o
+OBJS	+= misc.o decompress.o arch.o arch_reloc.o
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 # string library code (-Os is enforced to keep it much smaller)
Index: b/arch/arm/boot/compressed/vmlinux.lds.in
===================================================================
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -30,6 +30,9 @@ SECTIONS
     _start = .;
     *(.start)
     *(.text)
+    . = ALIGN(4);
+    __decomp_text_begin = .;
+    *(.text.decomp)
     *(.text.*)
     *(.fixup)
     *(.gnu.warning)
@@ -39,6 +42,12 @@ SECTIONS
   .rodata : {
     *(.rodata)
     *(.rodata.*)
+    . = ALIGN(4);
+    __decomp_tags_begin = .;
+    *(.init.decomp.tags)
+    __decomp_tags_end = .;
+    __decomp_data_begin = .;
+    *(.init.decomp.data)
   }
   .piggydata : {
     *(.piggydata)
Index: b/arch/arm/kernel/vmlinux.lds.S
===================================================================
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -111,6 +111,11 @@ SECTIONS
 		*(.got)			/* Global offset table		*/
 			ARM_CPU_KEEP(PROC_INFO)
 	}
+	.text.decomp : {
+		__decomp_text_begin = .;
+		LONG(__decomp_text_begin)
+		*(.arch.text.decomp)
+	}
 
 	RO_DATA(PAGE_SIZE)
 
@@ -150,6 +155,17 @@ SECTIONS
 		*(.arch.info.init)
 		__arch_info_end = .;
 	}
+	.init.decomp.tags : {
+		__decomp_tags_begin = .;
+		*(.arch.tags.decomp)
+		__decomp_tags_end = .;
+	}
+	.init.decomp.data : {
+		__decomp_data_begin = .;
+		LONG(__decomp_data_begin)
+		*(.arch.data.decomp)
+		__decomp_data_end = .;
+	}
 	.init.tagtable : {
 		__tagtable_begin = .;
 		*(.taglist.init)
Index: b/arch/arm/boot/compressed/arch.c
===================================================================
--- /dev/null
+++ b/arch/arm/boot/compressed/arch.c
@@ -0,0 +1,38 @@
+/*
+ * Decompressor arch specific stuff
+ *
+ * Copyright (C) 2012 Domenico Andreoli <[email-masked]>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+
+#include "arch.h"
+
+/* defined in the linker script */
+extern void *__decomp_text_begin;
+extern void *__decomp_data_begin;
+
+const void *fix_text_ptr(const void *p)
+{
+	if (!p)
+		return NULL;
+
+	return ((void *) &__decomp_text_begin) + (p - __decomp_text_begin);
+}
+
+const void *fix_data_ptr(const void *p)
+{
+	if (!p)
+		return NULL;
+
+	return ((void *) &__decomp_data_begin) + (p - __decomp_data_begin);
+}
Index: b/arch/arm/boot/compressed/arch.h
===================================================================
--- /dev/null
+++ b/arch/arm/boot/compressed/arch.h
@@ -0,0 +1,22 @@
+/*
+ * Common definitions used in the decompressor arch stuff
+ *
+ * Copyright (C) 2012 Domenico Andreoli <[email-masked]>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef ARM_BOOT_COMPRESSED_ARCH_H
+#define ARM_BOOT_COMPRESSED_ARCH_H
+
+const void *fix_text_ptr(const void *p);
+const void *fix_data_ptr(const void *p);
+
+#endif /* ARM_BOOT_COMPRESSED_ARCH_H */