public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Kumar Gala <galak@kernel.crashing.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [WIP][PATCH 09/11] bootm: refactor image detection and os load steps
Date: Tue, 12 Aug 2008 08:44:34 -0500	[thread overview]
Message-ID: <1218548676-25159-10-git-send-email-galak@kernel.crashing.org> (raw)
In-Reply-To: <1218548676-25159-9-git-send-email-galak@kernel.crashing.org>

Created a bootm_start() that handles the parsing and detection of all the
images that will be used by the bootm command (OS, ramdisk, fdt). As part
of this we now tract all the relevant image offsets in the bootm_headers_t
struct.  This will allow us to have all the needed state for future
sub-commands and lets us reduce a bit of arch specific code on SPARC.

Created a bootm_load_os() that deals with decompression and loading the
OS image.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 common/cmd_bootm.c |  219 ++++++++++++++++++++++++++++++---------------------
 include/image.h    |    9 ++
 lib_sparc/bootm.c  |   19 +----
 3 files changed, 139 insertions(+), 108 deletions(-)

diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 598f5af..adab88f 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -151,24 +151,16 @@ 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;
 
+	if (images.valid)
+		return 0;
+
 	memset ((void *)&images, 0, sizeof (images));
 	images.verify = getenv_yesno ("verify");
 
@@ -183,8 +175,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;
 	}
@@ -192,40 +184,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;
@@ -254,7 +246,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);
@@ -276,64 +268,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);
-
-	/*
-	 * 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();
+	images.os.start = (ulong)os_hdr;
+	images.valid = 1;
 
-#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:
@@ -343,51 +323,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@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 1975012..4fa8425 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 {
 #endif
 
 	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 aac05e4..f3abdcf 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;
-- 
1.5.5.1

  reply	other threads:[~2008-08-12 13:44 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-12 13:44 [U-Boot] [WIP][PATCH 00/11] bootm refactoring Kumar Gala
2008-08-12 13:44 ` [U-Boot] [WIP][PATCH 01/11] Update linux bootm to support ePAPR client interface Kumar Gala
2008-08-12 13:44   ` [U-Boot] [WIP][PATCH 02/11] add ability to disable ft_board_setup as part of bootm Kumar Gala
2008-08-12 13:44     ` [U-Boot] [WIP][PATCH 03/11] Clean up usage of icache_disable/dcache_disable Kumar Gala
2008-08-12 13:44       ` [U-Boot] [WIP][PATCH 04/11] bootm: refactor entry point code Kumar Gala
2008-08-12 13:44         ` [U-Boot] [WIP][PATCH 05/11] bootm: refactor ramdisk locating code Kumar Gala
2008-08-12 13:44           ` [U-Boot] [WIP][PATCH 06/11] bootm: refactor fdt locating and relocation code Kumar Gala
2008-08-12 13:44             ` [U-Boot] [WIP][PATCH 07/11] bootm: Set working fdt address as part of the bootm flow Kumar Gala
2008-08-12 13:44               ` [U-Boot] [WIP][PATCH 08/11] bootm: move lmb into the bootm_headers_t structure Kumar Gala
2008-08-12 13:44                 ` Kumar Gala [this message]
2008-08-12 13:44                   ` [U-Boot] [WIP][PATCH 10/11] fdt: refactor fdt resize code Kumar Gala
2008-08-12 13:44                     ` [U-Boot] [WIP][PATCH 11/11] fdt: refactor initrd related code Kumar Gala
2008-08-13  5:12                   ` [U-Boot] [WIP][PATCH 09/11] bootm: refactor image detection and os load steps Jerry Van Baren
2008-08-12 20:12 ` [U-Boot] [WIP][PATCH 00/11] bootm refactoring Wolfgang Denk
2008-08-12 20:17   ` Kumar Gala
2008-08-12 23:15     ` Wolfgang Denk
2008-08-13  1:01       ` Kumar Gala
2008-08-13  5:12         ` Jerry Van Baren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1218548676-25159-10-git-send-email-galak@kernel.crashing.org \
    --to=galak@kernel.crashing.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox