diff --git a/README b/README
index 92a11b4e11fc53f251ff235d2313e6aeb3565959..a9dc69bae0592c99544c575c01dd251b9deff0a1 100644
--- a/README
+++ b/README
@@ -3609,6 +3609,7 @@ go	- start application at address 'addr'
 run	- run commands in an environment variable
 bootm	- boot application image from memory
 bootp	- boot image via network using BootP/TFTP protocol
+bootz   - boot zImage from memory
 tftpboot- boot image via network using TFTP protocol
 	       and env variables "ipaddr" and "serverip"
 	       (and eventually "gatewayip")
@@ -4429,6 +4430,13 @@ U-Boot supports the following image types:
 	useful when you configure U-Boot to use a real shell (hush)
 	as command interpreter.
 
+Booting the Linux zImage:
+-------------------------
+
+On some platforms, it's possible to boot Linux zImage. This is done
+using the "bootz" command. The syntax of "bootz" command is the same
+as the syntax of "bootm" command.
+
 
 Standalone HOWTO:
 =================
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 160ba55111177f3f3f803c159e43ab2c9744fde4..1c1bee6aeb135251eac353783a6fb76196c2961a 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -359,3 +359,33 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
 	boot_jump_linux(images);
 	return 0;
 }
+
+#ifdef CONFIG_CMD_BOOTZ
+
+struct zimage_header {
+	uint32_t	code[9];
+	uint32_t	zi_magic;
+	uint32_t	zi_start;
+	uint32_t	zi_end;
+};
+
+#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818
+
+int bootz_setup(void *image, void **start, void **end)
+{
+	struct zimage_header *zi = (struct zimage_header *)image;
+
+	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
+		puts("Bad Linux ARM zImage magic!\n");
+		return 1;
+	}
+
+	*start = (void *)zi->zi_start;
+	*end = (void *)zi->zi_end;
+
+	debug("Kernel image @ 0x%08x [ 0x%08x - 0x%08x ]\n",
+		(uint32_t)image, (uint32_t)*start, (uint32_t)*end);
+
+	return 0;
+}
+#endif	/* CONFIG_CMD_BOOTZ */
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index d88f6c0253a1f0c8d12caaab61b127dd49391de6..5e5d572ebf294397fed0015efbfdb841ea3cf64f 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -169,25 +169,25 @@ void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
 
 #define IH_INITRD_ARCH IH_ARCH_DEFAULT
 
-static void bootm_start_lmb(void)
-{
 #ifdef CONFIG_LMB
+static void boot_start_lmb(bootm_headers_t *images)
+{
 	ulong		mem_start;
 	phys_size_t	mem_size;
 
-	lmb_init(&images.lmb);
+	lmb_init(&images->lmb);
 
 	mem_start = getenv_bootm_low();
 	mem_size = getenv_bootm_size();
 
-	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
+	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
 
-	arch_lmb_reserve(&images.lmb);
-	board_lmb_reserve(&images.lmb);
+	arch_lmb_reserve(&images->lmb);
+	board_lmb_reserve(&images->lmb);
+}
 #else
-# define lmb_reserve(lmb, base, size)
+static inline void boot_start_lmb(bootm_headers_t *images) { }
 #endif
-}
 
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -197,7 +197,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 	memset((void *)&images, 0, sizeof(images));
 	images.verify = getenv_yesno("verify");
 
-	bootm_start_lmb();
+	boot_start_lmb(&images);
 
 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
 
@@ -1518,3 +1518,126 @@ static int do_bootm_integrity(int flag, int argc, char * const argv[],
 	return 1;
 }
 #endif
+
+#ifdef CONFIG_CMD_BOOTZ
+
+static int __bootz_setup(void *image, void **start, void **end)
+{
+	/* Please define bootz_setup() for your platform */
+
+	puts("Your platform's zImage format isn't supported yet!\n");
+	return -1;
+}
+int bootz_setup(void *image, void **start, void **end)
+	__attribute__((weak, alias("__bootz_setup")));
+
+/*
+ * zImage booting support
+ */
+static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[], bootm_headers_t *images)
+{
+	int ret;
+	void *zi_start, *zi_end;
+
+	memset(images, 0, sizeof(bootm_headers_t));
+
+	boot_start_lmb(images);
+
+	/* Setup Linux kernel zImage entry point */
+	if (argc < 2) {
+		images->ep = load_addr;
+		debug("*  kernel: default image load address = 0x%08lx\n",
+				load_addr);
+	} else {
+		images->ep = simple_strtoul(argv[1], NULL, 16);
+		debug("*  kernel: cmdline image address = 0x%08lx\n",
+			images->ep);
+	}
+
+	ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
+	if (ret != 0)
+		return 1;
+
+	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
+
+	/* Find ramdisk */
+	ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
+			&images->rd_start, &images->rd_end);
+	if (ret) {
+		puts("Ramdisk image is corrupt or invalid\n");
+		return 1;
+	}
+
+#if defined(CONFIG_OF_LIBFDT)
+	/* find flattened device tree */
+	ret = boot_get_fdt(flag, argc, argv, images,
+			   &images->ft_addr, &images->ft_len);
+	if (ret) {
+		puts("Could not find a valid device tree\n");
+		return 1;
+	}
+
+	set_working_fdt_addr(images->ft_addr);
+#endif
+
+	return 0;
+}
+
+static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	ulong		iflag;
+	bootm_headers_t	images;
+
+	if (bootz_start(cmdtp, flag, argc, argv, &images))
+		return 1;
+
+	/*
+	 * We have reached the point of no return: we are going to
+	 * overwrite all exception vector code, so we cannot easily
+	 * recover from any failures any more...
+	 */
+	iflag = disable_interrupts();
+
+#if defined(CONFIG_CMD_USB)
+	/*
+	 * turn off USB to prevent the host controller from writing to the
+	 * SDRAM while Linux is booting. This could happen (at least for OHCI
+	 * controller), because the HCCA (Host Controller Communication Area)
+	 * lies within the SDRAM and the host controller writes continously to
+	 * this area (as busmaster!). The HccaFrameNumber is for example
+	 * updated every 1 ms within the HCCA structure in SDRAM! For more
+	 * details see the OpenHCI specification.
+	 */
+	usb_stop();
+#endif
+
+#ifdef CONFIG_SILENT_CONSOLE
+	fixup_silent_linux();
+#endif
+	arch_preboot_os();
+
+	do_bootm_linux(0, argc, argv, &images);
+#ifdef DEBUG
+	puts("\n## Control returned to monitor - resetting...\n");
+#endif
+	do_reset(cmdtp, flag, argc, argv);
+
+	return 1;
+}
+
+U_BOOT_CMD(
+	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
+	"boot Linux zImage image from memory",
+	"[addr [initrd] [fdt]]\n    - boot Linux zImage stored in memory\n"
+	"\tThe argument 'initrd' is optional and specifies the address\n"
+	"\tof the initrd in memory.\n"
+#if defined(CONFIG_OF_LIBFDT)
+	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
+	"\ta third argument is required which is the address of the\n"
+	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
+	"\tuse a '-' for the second argument. If you do not pass a third\n"
+	"\ta bd_info struct will be passed instead\n"
+#endif
+);
+#endif	/* CONFIG_CMD_BOOTZ */
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 9716f9cad47ae93b563d3303e17f51a4a1203333..2c6b8295fb88f1c5a673bfb1c08f86a667c92fb2 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -20,6 +20,7 @@
 #define CONFIG_CMD_BEDBUG	/* Include BedBug Debugger	*/
 #define CONFIG_CMD_BMP		/* BMP support			*/
 #define CONFIG_CMD_BOOTD	/* bootd			*/
+#define CONFIG_CMD_BOOTZ	/* boot zImage			*/
 #define CONFIG_CMD_BSP		/* Board Specific functions	*/
 #define CONFIG_CMD_CACHE	/* icache, dcache		*/
 #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/