Patchwork [U-Boot,1/1] Spi Flash: Allow auto-booting of images from spi flash load

login
register
mail settings
Submitter Andre Renaud
Date July 6, 2011, 9:51 p.m.
Message ID <4E14D8FE.9@bluewatersys.com>
Download mbox | patch
Permalink /patch/103583/
State Changes Requested
Headers show

Comments

Andre Renaud - July 6, 2011, 9:51 p.m.
This allows intelligent booting of FIT (& the legacy style) images from
SPI flash. Basically it means that you don't have to guess at the image 
length, so data reads are more optimal (& hopefully faster).

Signed-off-by: Andre Renaud <andre@bluewatersys.com>
---
Mike Frysinger - July 6, 2011, 10:14 p.m.
On Wednesday, July 06, 2011 17:51:58 Andre Renaud wrote:
> This allows intelligent booting of FIT (& the legacy style) images from
> SPI flash. Basically it means that you don't have to guess at the image
> length, so data reads are more optimal (& hopefully faster).

this looks like largely a copy & paste job from one of the many existing boot 
funcs.  considering the only unique thing here is the spi flash read, seems 
like it'd make sense to add a new func to common/cmd_bootm.c like 
bootm_load_image().  it'd take a read callback as well as a pointer to data.

as it stands, this patch breaks configs that enable the spi flash command but 
disable the bootm command.
-mike

Patch

Index: common/cmd_sf.c
===================================================================
--- common/cmd_sf.c	(revision 31)
+++ common/cmd_sf.c	(working copy)
@@ -109,6 +109,96 @@ 
 	return 0;
 }
 
+static int do_spi_flash_boot(cmd_tbl_t *cmdtp, int argc, char * const argv[])
+{
+	char *ep;
+	size_t cnt;
+	image_header_t *hdr;
+#if defined(CONFIG_FIT)
+	const void *fit_hdr = NULL;
+#endif
+	unsigned long addr;
+	unsigned long offset;
+	char *endp;
+	int ret;
+
+	if (argc < 3)
+		return -1;
+
+	addr = simple_strtoul(argv[1], &endp, 16);
+	if (*argv[1] == 0 || *endp != 0)
+		return -1;
+	offset = simple_strtoul(argv[2], &endp, 16);
+	if (*argv[2] == 0 || *endp != 0)
+		return -1;
+
+	printf("\nLoading from offset 0x%lx\n", offset);
+
+	ret = spi_flash_read(flash, offset, 1024, (u_char *)addr);
+	if (ret) {
+		printf("SPI flash boot failed\n");
+		return 1;
+	}
+
+	switch (genimg_get_format((void *)addr)) {
+	case IMAGE_FORMAT_LEGACY:
+		hdr = (image_header_t *)addr;
+
+		image_print_contents(hdr);
+
+		cnt = image_get_image_size(hdr);
+		break;
+#if defined(CONFIG_FIT)
+	case IMAGE_FORMAT_FIT:
+		fit_hdr = (const void *)addr;
+		puts("Fit image detected...\n");
+
+		cnt = fit_get_size(fit_hdr);
+		break;
+#endif
+	default:
+		puts("** Unknown image type\n");
+		return 1;
+	}
+
+	ret = spi_flash_read(flash, offset, cnt, (u_char *)addr);
+	if (ret) {
+		printf("SPI flash boot failed\n");
+		return 1;
+	}
+
+#if defined(CONFIG_FIT)
+	/* This cannot be done earlier,
+	 * we need complete FIT image in RAM first */
+	if (genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) {
+		if (!fit_check_format(fit_hdr)) {
+			puts("** Bad FIT image format\n");
+			return 1;
+		}
+		fit_print_contents(fit_hdr);
+	}
+#endif
+
+	/* Loading ok, update default load address */
+
+	load_addr = addr;
+
+	/* Check if we should attempt an auto-start */
+	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
+		char *local_args[2];
+
+		local_args[0] = "bootm";
+		local_args[1] = NULL;
+
+		printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+		do_bootm(cmdtp, 0, 1, local_args);
+		return 1;
+	}
+	return 0;
+}
+
+
 static int do_spi_flash_read_write(int argc, char * const argv[])
 {
 	unsigned long addr;
@@ -207,6 +297,8 @@ 
 		ret = do_spi_flash_read_write(argc, argv);
 	else if (strcmp(cmd, "erase") == 0)
 		ret = do_spi_flash_erase(argc, argv);
+	else if (strcmp(cmd, "boot") == 0)
+		ret = do_spi_flash_boot(cmdtp, argc, argv);
 	else
 		ret = -1;
 
@@ -229,4 +321,7 @@ 
 	"				  at `addr' to flash at `offset'\n"
 	"sf erase offset [+]len		- erase `len' bytes from `offset'\n"
 	"				  `+len' round up `len' to block size"
+	"sf boot addr offset            - read a boot image starting at\n"
+	"                                 `offset' to memory at `addr' and\n"
+	"                                 execute it\n"
 );