diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index dc88e6307b6fc619765b884d81e5f2add2a5d72c..5f7458b80a3e80615cad943f8a30fa1bbfe2ded3 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -150,22 +150,11 @@ void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_
 # error Unknown CPU type
 #endif
 
-/*******************************************************************/
-/* bootm - boot application image from image in memory */
-/*******************************************************************/
-int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong		iflag;
-	const char	*type_name;
-	uint		unc_len = CFG_BOOTM_LEN;
-	uint8_t		comp, type, os;
-
-	void		*os_hdr;
-	ulong		os_data, os_len;
-	ulong		image_start, image_end;
-	ulong		load_start, load_end;
 	ulong		mem_start;
 	phys_size_t	mem_size;
+	void		*os_hdr;
 	int		ret;
 
 	memset ((void *)&images, 0, sizeof (images));
@@ -182,8 +171,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
 	/* get kernel image header, start address and length */
 	os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,
-			&images, &os_data, &os_len);
-	if (os_len == 0) {
+			&images, &images.os.image_start, &images.os.image_len);
+	if (images.os.image_len == 0) {
 		puts ("ERROR: can't get kernel image!\n");
 		return 1;
 	}
@@ -191,40 +180,40 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	/* get image parameters */
 	switch (genimg_get_format (os_hdr)) {
 	case IMAGE_FORMAT_LEGACY:
-		type = image_get_type (os_hdr);
-		comp = image_get_comp (os_hdr);
-		os = image_get_os (os_hdr);
+		images.os.type = image_get_type (os_hdr);
+		images.os.comp = image_get_comp (os_hdr);
+		images.os.os = image_get_os (os_hdr);
 
-		image_end = image_get_image_end (os_hdr);
-		load_start = image_get_load (os_hdr);
+		images.os.end = image_get_image_end (os_hdr);
+		images.os.load = image_get_load (os_hdr);
 		break;
 #if defined(CONFIG_FIT)
 	case IMAGE_FORMAT_FIT:
 		if (fit_image_get_type (images.fit_hdr_os,
-					images.fit_noffset_os, &type)) {
+					images.fit_noffset_os, &images.os.type)) {
 			puts ("Can't get image type!\n");
 			show_boot_progress (-109);
 			return 1;
 		}
 
 		if (fit_image_get_comp (images.fit_hdr_os,
-					images.fit_noffset_os, &comp)) {
+					images.fit_noffset_os, &images.os.comp)) {
 			puts ("Can't get image compression!\n");
 			show_boot_progress (-110);
 			return 1;
 		}
 
 		if (fit_image_get_os (images.fit_hdr_os,
-					images.fit_noffset_os, &os)) {
+					images.fit_noffset_os, &images.os.os)) {
 			puts ("Can't get image OS!\n");
 			show_boot_progress (-111);
 			return 1;
 		}
 
-		image_end = fit_get_end (images.fit_hdr_os);
+		images.os.end = fit_get_end (images.fit_hdr_os);
 
 		if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os,
-					&load_start)) {
+					&images.os.load)) {
 			puts ("Can't get image load address!\n");
 			show_boot_progress (-112);
 			return 1;
@@ -253,7 +242,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		return 1;
 	}
 
-	if (os == IH_OS_LINUX) {
+	if (images.os.os == IH_OS_LINUX) {
 		/* find ramdisk */
 		ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH,
 				&images.rd_start, &images.rd_end);
@@ -275,64 +264,52 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 #endif
 	}
 
-	image_start = (ulong)os_hdr;
-	load_end = 0;
-	type_name = genimg_get_type_name (type);
+	images.os.start = (ulong)os_hdr;
+	images.valid = 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
+	return 0;
+}
 
+#define BOOTM_ERR_RESET		-1
+#define BOOTM_ERR_OVERLAP	-2
+#define BOOTM_ERR_UNIMPLEMENTED	-3
+static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
+{
+	uint8_t comp = os.comp;
+	ulong load = os.load;
+	ulong blob_start = os.start;
+	ulong blob_end = os.end;
+	ulong image_start = os.image_start;
+	ulong image_len = os.image_len;
+	uint unc_len = CFG_BOOTM_LEN;
 
-#ifdef CONFIG_AMIGAONEG3SE
-	/*
-	 * We've possible left the caches enabled during
-	 * bios emulation, so turn them off again
-	 */
-	icache_disable();
-	dcache_disable();
-#endif
+	const char *type_name = genimg_get_type_name (os.type);
 
 	switch (comp) {
 	case IH_COMP_NONE:
-		if (load_start == (ulong)os_hdr) {
+		if (load == blob_start) {
 			printf ("   XIP %s ... ", type_name);
 		} else {
 			printf ("   Loading %s ... ", type_name);
 
-			memmove_wd ((void *)load_start,
-				   (void *)os_data, os_len, CHUNKSZ);
+			memmove_wd ((void *)load,
+				   (void *)image_start, image_len, CHUNKSZ);
 		}
-		load_end = load_start + os_len;
+		*load_end = load + image_len;
 		puts("OK\n");
 		break;
 	case IH_COMP_GZIP:
 		printf ("   Uncompressing %s ... ", type_name);
-		if (gunzip ((void *)load_start, unc_len,
-					(uchar *)os_data, &os_len) != 0) {
+		if (gunzip ((void *)load, unc_len,
+					(uchar *)image_start, &image_len) != 0) {
 			puts ("GUNZIP: uncompress or overwrite error "
 				"- must RESET board to recover\n");
-			show_boot_progress (-6);
-			do_reset (cmdtp, flag, argc, argv);
+			if (boot_progress)
+				show_boot_progress (-6);
+			return BOOTM_ERR_RESET;
 		}
 
-		load_end = load_start + os_len;
+		*load_end = load + image_len;
 		break;
 #ifdef CONFIG_BZIP2
 	case IH_COMP_BZIP2:
@@ -342,51 +319,110 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		 * use slower decompression algorithm which requires
 		 * at most 2300 KB of memory.
 		 */
-		int i = BZ2_bzBuffToBuffDecompress ((char*)load_start,
-					&unc_len, (char *)os_data, os_len,
+		int i = BZ2_bzBuffToBuffDecompress ((char*)load,
+					&unc_len, (char *)image_start, image_len,
 					CFG_MALLOC_LEN < (4096 * 1024), 0);
 		if (i != BZ_OK) {
 			printf ("BUNZIP2: uncompress or overwrite error %d "
 				"- must RESET board to recover\n", i);
-			show_boot_progress (-6);
-			do_reset (cmdtp, flag, argc, argv);
+			if (boot_progress)
+				show_boot_progress (-6);
+			return BOOTM_ERR_RESET;
 		}
 
-		load_end = load_start + unc_len;
+		*load_end = load + unc_len;
 		break;
 #endif /* CONFIG_BZIP2 */
 	default:
-		if (iflag)
-			enable_interrupts();
 		printf ("Unimplemented compression type %d\n", comp);
-		show_boot_progress (-7);
-		return 1;
+		return BOOTM_ERR_UNIMPLEMENTED;
 	}
 	puts ("OK\n");
-	debug ("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end);
-	show_boot_progress (7);
+	debug ("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end);
+	if (boot_progress)
+		show_boot_progress (7);
 
-	if ((load_start < image_end) && (load_end > image_start)) {
-		debug ("image_start = 0x%lX, image_end = 0x%lx\n", image_start, image_end);
-		debug ("load_start = 0x%lx, load_end = 0x%lx\n", load_start, load_end);
+	if ((load < blob_end) && (*load_end > blob_start)) {
+		debug ("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end);
+		debug ("images.os.load = 0x%lx, load_end = 0x%lx\n", load, load_end);
 
-		if (images.legacy_hdr_valid) {
-			if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
-				puts ("WARNING: legacy format multi component "
-					"image overwritten\n");
-		} else {
-			puts ("ERROR: new format image overwritten - "
-				"must RESET the board to recover\n");
-			show_boot_progress (-113);
+		return BOOTM_ERR_OVERLAP;
+	}
+
+	return 0;
+}
+
+/*******************************************************************/
+/* bootm - boot application image from image in memory */
+/*******************************************************************/
+int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+
+	ulong		iflag;
+	ulong		load_end = 0;
+	int		ret;
+
+	bootm_start(cmdtp, flag, argc, argv);
+
+	/*
+	 * 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_AMIGAONEG3SE
+	/*
+	 * We've possible left the caches enabled during
+	 * bios emulation, so turn them off again
+	 */
+	icache_disable();
+	dcache_disable();
+#endif
+
+	ret = bootm_load_os(images.os, &load_end, 1);
+
+	if (ret < 0) {
+		if (ret == BOOTM_ERR_RESET)
 			do_reset (cmdtp, flag, argc, argv);
+		if (ret == BOOTM_ERR_OVERLAP) {
+			if (images.legacy_hdr_valid) {
+				if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
+					puts ("WARNING: legacy format multi component "
+						"image overwritten\n");
+			} else {
+				puts ("ERROR: new format image overwritten - "
+					"must RESET the board to recover\n");
+				show_boot_progress (-113);
+				do_reset (cmdtp, flag, argc, argv);
+			}
+		}
+		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
+			if (iflag)
+				enable_interrupts();
+			show_boot_progress (-7);
+			return 1;
 		}
 	}
 
-	show_boot_progress (8);
+	lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
 
-	lmb_reserve(&images.lmb, load_start, (load_end - load_start));
+	show_boot_progress (8);
 
-	switch (os) {
+	switch (images.os.os) {
 	default:			/* handled by (original) Linux case */
 	case IH_OS_LINUX:
 #ifdef CONFIG_SILENT_CONSOLE
diff --git a/include/image.h b/include/image.h
index c1acd7b822f636e45ac62d839d9b56e9c78f94f5..9be806e12d7533033c7bd1f7b3358f8c11b1ed37 100644
--- a/include/image.h
+++ b/include/image.h
@@ -187,6 +187,13 @@ typedef struct image_header {
 	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
 } image_header_t;
 
+typedef struct image_info {
+	ulong		start, end;		/* start/end of blob */
+	ulong		image_start, image_len; /* start of image within blob, len of image */
+	ulong		load;			/* load addr for the image */
+	uint8_t		comp, type, os;		/* compression, type of image, os type */
+} image_info_t;
+
 /*
  * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>()
  * routines.
@@ -219,6 +226,7 @@ typedef struct bootm_headers {
 #endif
 #endif
 
+	image_info_t	os;		/* os image info */
 	ulong		ep;		/* entry point of OS */
 
 	ulong		rd_start, rd_end;/* ramdisk start/end */
@@ -229,6 +237,7 @@ typedef struct bootm_headers {
 	ulong		ft_len;		/* length of flat device tree */
 
 	int		verify;		/* getenv("verify")[0] != 'n' */
+	int		valid;		/* set to 1 if we've set values in the header */
 #ifndef USE_HOSTCC
 	struct lmb	lmb;		/* for memory mgmt */
 #endif
diff --git a/lib_sparc/bootm.c b/lib_sparc/bootm.c
index aac05e4b264f65a72c2e5b4a73d2732353b08b5e..f3abdcfdc412d416e69a5a2c92f2b5a738393952 100644
--- a/lib_sparc/bootm.c
+++ b/lib_sparc/bootm.c
@@ -87,7 +87,6 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
 		    bootm_headers_t * images)
 {
 	char *bootargs;
-	ulong load;
 	ulong initrd_start, initrd_end;
 	ulong rd_len;
 	unsigned int data, len, checksum;
@@ -96,24 +95,8 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
 	struct lmb *lmb = &images->lmb;
 	int ret;
 
-	if (images->legacy_hdr_valid) {
-		load = image_get_load(images->legacy_hdr_os);
-#if defined(CONFIG_FIT)
-	} else if (images->fit_uname_os) {
-		ret = fit_image_get_load(images->fit_hdr_os,
-					 images->fit_noffset_os, &load);
-		if (ret) {
-			puts("Can't get load address property!\n");
-			goto error;
-		}
-#endif
-	} else {
-		puts("Could not find kernel entry point!\n");
-		goto error;
-	}
-
 	/* Get virtual address of kernel start */
-	linux_hdr = (void *)load;
+	linux_hdr = (void *)images->os.load;
 
 	/* */
 	kernel = (void (*)(struct linux_romvec *, void *))images->ep;