diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index bb26756..e4ef227 100644
--- 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 move_ramdisk.o
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 # string library code (-Os is enforced to keep it much smaller)
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 8e2a8fc..df1df60 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -22,7 +22,8 @@ unsigned int __machine_arch_type;
 #include <linux/types.h>
 #include <linux/linkage.h>
 
-static void putstr(const char *ptr);
+extern void move_ramdisk(void);
+extern void putstr(const char *ptr);
 extern void error(char *x);
 
 #include <mach/uncompress.h>
@@ -83,7 +84,7 @@ static void icedcc_putc(int ch)
 #define putc(ch)	icedcc_putc(ch)
 #endif
 
-static void putstr(const char *ptr)
+void putstr(const char *ptr)
 {
 	char c;
 
@@ -144,6 +145,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 
 	arch_decomp_setup();
 
+	move_ramdisk();
+
 	putstr("Uncompressing Linux...");
 	ret = do_decompress(input_data, input_data_end - input_data,
 			    output_data, error);
diff --git a/arch/arm/boot/compressed/move_ramdisk.c b/arch/arm/boot/compressed/move_ramdisk.c
new file mode 100644
index 0000000..b984433
--- /dev/null
+++ b/arch/arm/boot/compressed/move_ramdisk.c
@@ -0,0 +1,61 @@
+/*
+ * move_ramdisk.c
+ *
+ * Author: Wu Zhangjin, wuzhangjin@gmail.com, December 2013
+ * Copyright: (C) 2013 Meizu Telecom Equipment Co., Ltd
+ *
+ * Please get help of MOVE_RAMDISK from usr/Kconfig.
+ */
+
+
+#include "move_ramdisk.h"
+
+extern void putstr(const char *ptr);
+
+void move_ramdisk(void)
+{
+#if defined(CONFIG_MOVE_RAMDISK) && defined(TAG_BASE_ADDR)
+	struct tag *tags = (struct tag *)(TAG_BASE_ADDR);
+	__u32 start, target, size;
+	int found = 0, type = 0;
+
+	putstr("Searching ramdisk ...\n");
+	if (tags->hdr.tag == ATAG_CORE) {
+		putstr("Found tags ...\n");
+		for (tags = tag_next(tags); tags->hdr.size; tags = tag_next(tags)) {
+			if (tags->hdr.tag == ATAG_INITRD2) {
+				putstr("Found initrd2 tag ...\n");
+				found = 1;
+				break;
+			} else if (tags->hdr.tag == ATAG_INITRD) {
+				putstr("Found initrd tag ...\n");
+				found = 1;
+				break;
+			} else if (tags->hdr.tag == ATAG_RAMDISK) {
+				putstr("Found ramdisk tag ...\n");
+				found = 1;
+				type = 1;
+				break;
+			}
+		}
+		if (found) {
+			if (type == 0) {
+				start = tags->u.initrd.start;
+				size = tags->u.initrd.size;
+				target = start + MOVE_RAMDISK_OFFSET;
+				tags->u.initrd.start = target;
+			} else {
+				start = tags->u.ramdisk.start;
+				size = tags->u.ramdisk.size;
+				target = start + MOVE_RAMDISK_OFFSET;
+				tags->u.ramdisk.start = target;
+			}
+
+			putstr("Moving ramdisk forward ...\n");
+			memcpy((char *)target, (char *)start, size + SIZE_FIXUP_OFFSET);
+		}
+	} else {
+		putstr("No tag found ...\n");
+	}
+#endif
+}
diff --git a/arch/arm/boot/compressed/move_ramdisk.h b/arch/arm/boot/compressed/move_ramdisk.h
new file mode 100644
index 0000000..b824cde
--- /dev/null
+++ b/arch/arm/boot/compressed/move_ramdisk.h
@@ -0,0 +1,35 @@
+#ifndef _MOVE_RAMDISK_H
+#define _MOVE_RAMDISK_H
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/string.h>
+
+/* The physical base address of your platform, see PHYS_OFFSET */
+#ifdef PLAT_PHYS_OFFSET
+#define __PLAT_PHYS_OFFSET	(PLAT_PHYS_OFFSET)
+#else
+
+#ifdef defined (CONFIG_ARCH_ORION5X) || defined (CONFIG_ARCH_KIRKWOOD)
+#define __PLAT_PHYS_OFFSET    UL(0x00000000)
+#else
+#error "Please define __PLAT_PHYS_OFFSET, the physical base address of DRAM"
+#endif
+
+#endif /* PLAT_PHYS_OFFSET */
+
+/* Most boards put tag at the offset 0x100 with the base PHYS_OFFSET */
+#define TAG_BASE_OFFSET		(0x100)
+
+/* The tag address */
+#ifdef __PLAT_PHYS_OFFSET
+#define TAG_BASE_ADDR		(__PLAT_PHYS_OFFSET + TAG_BASE_OFFSET)
+#endif
+
+/* Some old Uboot pass the wrong size to kernel, fix up it with an offset. */
+#define SIZE_FIXUP_OFFSET	(1024)
+
+#define MOVE_RAMDISK_OFFSET	(CONFIG_MOVE_RAMDISK_OFFSET_M * 1024 * 1024)
+#define tag_next(t)	((struct tag *)((__u32 *)(t) + (t)->hdr.size))
+
+#endif /* _MOVE_RAMDISK_H */
diff --git a/usr/Kconfig b/usr/Kconfig
index 65b845b..ad5ce5b 100644
--- a/usr/Kconfig
+++ b/usr/Kconfig
@@ -166,3 +166,32 @@ config INITRAMFS_COMPRESSION_LZO
 	  (both compression and decompression) is the fastest.
 
 endchoice
+
+config MOVE_RAMDISK
+	bool "Move ramdisk forward to reserve more memory for kernel image"
+	depends on ARM
+	help
+	  During embedded linux system booting, before decompressing the kernel
+	  image, the bootloader(E.g. Uboot) loads the compressed kernel image
+	  and ramdisk into two contiguous memory space, these two memory space
+	  are fixed after the Uboot is released, as a result, the maximum size
+	  of the decompressed kernel image is limited by the size of the
+	  reserved memory space (the difference of the two contiguous memory
+	  addresses).
+
+	  If want more functions or some debug options, the decompressed kernel
+	  image may be bigger and may override the followed ramdisk and result
+	  in kernel boot failure for missing a valid ramdisk.
+
+	  To fix up this issue, before decompressing the kernel image, this
+	  option moves the loaded ramdisk image forward with a specified offset
+	  and reserve more memory for the decompressed kernel image.
+
+config MOVE_RAMDISK_OFFSET_M
+	int "Set the move offset of ramdisk (in Mbytes)"
+	range 5 100
+	default "20"
+	depends on MOVE_RAMDISK
+	help
+	  Specify the move offset of the ramdisk, if want a bigger kernel, please
+	  Increase this size.
