diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/Makefile | 3 | ||||
| -rw-r--r-- | common/cmd_autoscript.c | 153 | ||||
| -rw-r--r-- | common/cmd_bootm.c | 1943 | ||||
| -rw-r--r-- | common/cmd_doc.c | 38 | ||||
| -rw-r--r-- | common/cmd_fdc.c | 59 | ||||
| -rw-r--r-- | common/cmd_fpga.c | 107 | ||||
| -rw-r--r-- | common/cmd_ide.c | 58 | ||||
| -rw-r--r-- | common/cmd_load.c | 11 | ||||
| -rw-r--r-- | common/cmd_nand.c | 80 | ||||
| -rw-r--r-- | common/cmd_net.c | 11 | ||||
| -rw-r--r-- | common/cmd_scsi.c | 47 | ||||
| -rw-r--r-- | common/cmd_usb.c | 50 | ||||
| -rw-r--r-- | common/cmd_ximg.c | 166 | ||||
| -rw-r--r-- | common/gunzip.c | 113 | ||||
| -rw-r--r-- | common/image.c | 2541 | ||||
| -rw-r--r-- | common/lynxkdi.c | 46 | 
16 files changed, 3963 insertions, 1463 deletions
| diff --git a/common/Makefile b/common/Makefile index 56176ca2a..1c81fcfe4 100644 --- a/common/Makefile +++ b/common/Makefile @@ -36,6 +36,8 @@ COBJS-y += cmd_autoscript.o  COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o  COBJS-$(CONFIG_CMD_BEDBUG) += cmd_bedbug.o  COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o +COBJS-y += image.o +COBJS-y += gunzip.o  COBJS-y += cmd_boot.o  COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o  COBJS-y += cmd_bootm.o @@ -94,6 +96,7 @@ COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o  COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o  COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o  COBJS-$(CONFIG_CMD_USB) += cmd_usb.o +COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o  COBJS-y += cmd_vfd.o  COBJS-y += command.o  COBJS-y += console.o diff --git a/common/cmd_autoscript.c b/common/cmd_autoscript.c index a6038a6ef..1a37b90d7 100644 --- a/common/cmd_autoscript.c +++ b/common/cmd_autoscript.c @@ -49,57 +49,110 @@  #if defined(CONFIG_AUTOSCRIPT) || defined(CONFIG_CMD_AUTOSCRIPT) -extern image_header_t header;		/* from cmd_bootm.c */  int -autoscript (ulong addr) +autoscript (ulong addr, const char *fit_uname)  { -	ulong crc, data, len; -	image_header_t *hdr = &header; -	ulong *len_ptr; -	char *cmd; -	int rcode = 0; -	int verify; +	ulong 		len; +	image_header_t	*hdr; +	ulong		*data; +	char		*cmd; +	int		rcode = 0; +	int		verify; +#if defined(CONFIG_FIT) +	const void*	fit_hdr; +	int		noffset; +	const void	*fit_data; +	size_t		fit_len; +#endif -	cmd = getenv ("verify"); -	verify = (cmd && (*cmd == 'n')) ? 0 : 1; +	verify = getenv_verify (); +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; -	memmove (hdr, (char *)addr, sizeof(image_header_t)); +		if (!image_check_magic (hdr)) { +			puts ("Bad magic number\n"); +			return 1; +		} -	if (ntohl(hdr->ih_magic) != IH_MAGIC) { -		puts ("Bad magic number\n"); -		return 1; -	} +		if (!image_check_hcrc (hdr)) { +			puts ("Bad header crc\n"); +			return 1; +		} -	crc = ntohl(hdr->ih_hcrc); -	hdr->ih_hcrc = 0; -	len = sizeof (image_header_t); -	data = (ulong)hdr; -	if (crc32(0, (uchar *)data, len) != crc) { -		puts ("Bad header crc\n"); -		return 1; -	} +		if (verify) { +			if (!image_check_dcrc (hdr)) { +				puts ("Bad data crc\n"); +				return 1; +			} +		} -	data = addr + sizeof(image_header_t); -	len = ntohl(hdr->ih_size); +		if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { +			puts ("Bad image type\n"); +			return 1; +		} + +		/* get length of script */ +		data = (ulong *)image_get_data (hdr); -	if (verify) { -		if (crc32(0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { -			puts ("Bad data crc\n"); +		if ((len = uimage_to_cpu (*data)) == 0) { +			puts ("Empty Script\n");  			return 1;  		} -	} -	if (hdr->ih_type != IH_TYPE_SCRIPT) { -		puts ("Bad image type\n"); -		return 1; -	} +		/* +		 * scripts are just multi-image files with one component, seek +		 * past the zero-terminated sequence of image lengths to get +		 * to the actual image data +		 */ +		while (*data++); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		if (fit_uname == NULL) { +			puts ("No FIT subimage unit name\n"); +			return 1; +		} -	/* get length of script */ -	len_ptr = (ulong *)data; +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			puts ("Bad FIT image format\n"); +			return 1; +		} + +		/* get script component image node offset */ +		noffset = fit_image_get_node (fit_hdr, fit_uname); +		if (noffset < 0) { +			printf ("Can't find '%s' FIT subimage\n", fit_uname); +			return 1; +		} + +		if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { +			puts ("Not a image image\n"); +			return 1; +		} + +		/* verify integrity */ +		if (verify) { +			if (!fit_image_check_hashes (fit_hdr, noffset)) { +				puts ("Bad Data Hash\n"); +				return 1; +			} +		} -	if ((len = ntohl(*len_ptr)) == 0) { -		puts ("Empty Script\n"); +		/* get script subimage data address and length */ +		if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { +			puts ("Could not find script subimage data\n"); +			return 1; +		} + +		data = (ulong *)fit_data; +		len = (ulong)fit_len; +		break; +#endif +	default: +		puts ("Wrong image format for autoscript\n");  		return 1;  	} @@ -109,10 +162,8 @@ autoscript (ulong addr)  		return 1;  	} -	while (*len_ptr++); -  	/* make sure cmd is null terminated */ -	memmove (cmd, (char *)len_ptr, len); +	memmove (cmd, (char *)data, len);  	*(cmd + len) = 0;  #ifdef CFG_HUSH_PARSER /*?? */ @@ -158,25 +209,35 @@ do_autoscript (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  {  	ulong addr;  	int rcode; +	const char *fit_uname = NULL; +	/* Find script image */  	if (argc < 2) {  		addr = CFG_LOAD_ADDR; +		debug ("*  autoscr: default load address = 0x%08lx\n", addr); +#if defined(CONFIG_FIT) +	} else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) { +		debug ("*  autoscr: subimage '%s' from FIT image at 0x%08lx\n", +				fit_uname, addr); +#endif  	} else { -		addr = simple_strtoul (argv[1],0,16); +		addr = simple_strtoul(argv[1], NULL, 16); +		debug ("*  autoscr: cmdline image address = 0x%08lx\n", addr);  	} -	printf ("## Executing script at %08lx\n",addr); -	rcode = autoscript (addr); +	printf ("## Executing script at %08lx\n", addr); +	rcode = autoscript (addr, fit_uname);  	return rcode;  } -#if defined(CONFIG_CMD_AUTOSCRIPT)  U_BOOT_CMD(  	autoscr, 2, 0,	do_autoscript,  	"autoscr - run script from memory\n",  	"[addr] - run script starting at addr"  	" - A valid autoscr header must be present\n" -); +#if defined(CONFIG_FIT) +	"For FIT format uImage addr must include subimage\n" +	"unit name in the form of addr:<subimg_uname>\n"  #endif - +);  #endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 5a8572602..9e5ce4b38 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -21,6 +21,7 @@   * MA 02111-1307 USA   */ +  /*   * Boot support   */ @@ -32,56 +33,24 @@  #include <zlib.h>  #include <bzlib.h>  #include <environment.h> +#include <lmb.h>  #include <asm/byteorder.h> -#if defined(CONFIG_OF_LIBFDT) -#include <fdt.h> -#include <libfdt.h> -#include <fdt_support.h> -#endif -#if defined(CONFIG_OF_FLAT_TREE) -#include <ft_build.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) -#include <rtc.h> -#endif -  #ifdef CFG_HUSH_PARSER  #include <hush.h>  #endif -#ifdef CFG_INIT_RAM_LOCK -#include <asm/cache.h> -#endif - -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif +DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_HAS_DATAFLASH -#include <dataflash.h> +extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp); +#ifndef CFG_BOOTM_LEN +#define CFG_BOOTM_LEN	0x800000	/* use 8MByte as default max gunzip size */  #endif -/* - * Some systems (for example LWMON) have very short watchdog periods; - * we must make sure to split long operations like memmove() or - * crc32() into reasonable chunks. - */ -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -# define CHUNKSZ (64 * 1024) +#ifdef CONFIG_BZIP2 +extern void bz_internal_error(int);  #endif -int  gunzip (void *, int, unsigned char *, unsigned long *); - -static void *zalloc(void *, unsigned, unsigned); -static void zfree(void *, void *, unsigned); -  #if defined(CONFIG_CMD_IMI)  static int image_info (unsigned long addr);  #endif @@ -92,12 +61,19 @@ extern flash_info_t flash_info[]; /* info for FLASH chips */  static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);  #endif -static void print_type (image_header_t *hdr); +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux (void); +#endif -#ifdef __I386__ -image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); +static image_header_t *image_get_kernel (ulong img_addr, int verify); +#if defined(CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify);  #endif +static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[], +		bootm_headers_t *images, ulong *os_data, ulong *os_len); +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +  /*   *  Continue booting an OS image; caller already has:   *  - copied image header to global variable `header' @@ -106,203 +82,135 @@ image_header_t *fake_header(image_header_t *hdr, void *ptr, int size);   *  - loaded (first part of) image to header load address,   *  - disabled interrupts.   */ -typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag, -			  int	argc, char *argv[], -			  ulong	addr,		/* of image to boot */ -			  ulong	*len_ptr,	/* multi-file image length table */ -			  int	verify);	/* getenv("verify")[0] != 'n' */ - -#ifdef	DEBUG -extern int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); -#endif +typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag, +			int argc, char *argv[], +			bootm_headers_t *images); /* pointers to os/initrd/fdt */ -#ifdef CONFIG_PPC -static boot_os_Fcn do_bootm_linux; -#else -extern boot_os_Fcn do_bootm_linux; +extern boot_os_fn do_bootm_linux; +static boot_os_fn do_bootm_netbsd; +#if defined(CONFIG_LYNXKDI) +static boot_os_fn do_bootm_lynxkdi; +extern void lynxkdi_boot (image_header_t *);  #endif -#ifdef CONFIG_SILENT_CONSOLE -static void fixup_silent_linux (void); -#endif -static boot_os_Fcn do_bootm_netbsd; -static boot_os_Fcn do_bootm_rtems; +static boot_os_fn do_bootm_rtems;  #if defined(CONFIG_CMD_ELF) -static boot_os_Fcn do_bootm_vxworks; -static boot_os_Fcn do_bootm_qnxelf; -int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ); -int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ); +static boot_os_fn do_bootm_vxworks; +static boot_os_fn do_bootm_qnxelf; +int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);  #endif  #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) -static boot_os_Fcn do_bootm_artos; -#endif -#ifdef CONFIG_LYNXKDI -static boot_os_Fcn do_bootm_lynxkdi; -extern void lynxkdi_boot( image_header_t * ); +extern uchar (*env_get_char)(int); /* Returns a character from the environment */ +static boot_os_fn do_bootm_artos;  #endif -#ifndef CFG_BOOTM_LEN -#define CFG_BOOTM_LEN	0x800000	/* use 8MByte as default max gunzip size */ -#endif +ulong load_addr = CFG_LOAD_ADDR;	/* Default Load Address */ +static bootm_headers_t images;		/* pointers to os/initrd/fdt images */ -image_header_t header; +void __board_lmb_reserve(struct lmb *lmb) +{ +	/* please define platform specific board_lmb_reserve() */ +} +void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve"))); -ulong load_addr = CFG_LOAD_ADDR;		/* Default Load Address */ +/*******************************************************************/ +/* bootm - boot application image from image in memory */ +/*******************************************************************/  int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  { -	ulong	iflag; -	ulong	addr; -	ulong	data, len, checksum; -	ulong  *len_ptr; -	uint	unc_len = CFG_BOOTM_LEN; -	int	i, verify; -	char	*name, *s; -	int	(*appl)(int, char *[]); -	image_header_t *hdr = &header; +	ulong		iflag; +	const char	*type_name; +	uint		unc_len = CFG_BOOTM_LEN; +	uint8_t		comp, type, os; -	s = getenv ("verify"); -	verify = (s && (*s == 'n')) ? 0 : 1; +	void		*os_hdr; +	ulong		os_data, os_len; +	ulong		image_start, image_end; +	ulong		load_start, load_end; +	ulong		mem_start, mem_size; -	if (argc < 2) { -		addr = load_addr; -	} else { -		addr = simple_strtoul(argv[1], NULL, 16); -	} +	struct lmb lmb; -	show_boot_progress (1); -	printf ("## Booting image at %08lx ...\n", addr); +	memset ((void *)&images, 0, sizeof (images)); +	images.verify = getenv_verify(); +	images.autostart = getenv_autostart(); +	images.lmb = &lmb; -	/* Copy header so we can blank CRC field for re-calculation */ -#ifdef CONFIG_HAS_DATAFLASH -	if (addr_dataflash(addr)){ -		read_dataflash(addr, sizeof(image_header_t), (char *)&header); -	} else -#endif -	memmove (&header, (char *)addr, sizeof(image_header_t)); +	lmb_init(&lmb); -	if (ntohl(hdr->ih_magic) != IH_MAGIC) { -#ifdef __I386__	/* correct image format not implemented yet - fake it */ -		if (fake_header(hdr, (void*)addr, -1) != NULL) { -			/* to compensate for the addition below */ -			addr -= sizeof(image_header_t); -			/* turnof verify, -			 * fake_header() does not fake the data crc -			 */ -			verify = 0; -		} else -#endif	/* __I386__ */ -	    { -		puts ("Bad Magic Number\n"); -		show_boot_progress (-1); -		return 1; -	    } -	} -	show_boot_progress (2); +	mem_start = getenv_bootm_low(); +	mem_size = getenv_bootm_size(); -	data = (ulong)&header; -	len  = sizeof(image_header_t); +	lmb_add(&lmb, mem_start, mem_size); -	checksum = ntohl(hdr->ih_hcrc); -	hdr->ih_hcrc = 0; +	board_lmb_reserve(&lmb); -	if (crc32 (0, (uchar *)data, len) != checksum) { -		puts ("Bad Header Checksum\n"); -		show_boot_progress (-2); +	/* 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) { +		puts ("ERROR: can't get kernel image!\n");  		return 1;  	} -	show_boot_progress (3); - -#ifdef CONFIG_HAS_DATAFLASH -	if (addr_dataflash(addr)){ -		len  = ntohl(hdr->ih_size) + sizeof(image_header_t); -		read_dataflash(addr, len, (char *)CFG_LOAD_ADDR); -		addr = CFG_LOAD_ADDR; -	} -#endif - -	/* for multi-file images we need the data part, too */ -	print_image_hdr ((image_header_t *)addr); +	/* 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); -	data = addr + sizeof(image_header_t); -	len  = ntohl(hdr->ih_size); +		image_end = image_get_image_end (os_hdr); +		load_start = 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)) { +			puts ("Can't get image type!\n"); +			show_boot_progress (-109); +			return 1; +		} -	if (verify) { -		puts ("   Verifying Checksum ... "); -		if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { -			printf ("Bad Data CRC\n"); -			show_boot_progress (-3); +		if (fit_image_get_comp (images.fit_hdr_os, +					images.fit_noffset_os, &comp)) { +			puts ("Can't get image compression!\n"); +			show_boot_progress (-110);  			return 1;  		} -		puts ("OK\n"); -	} -	show_boot_progress (4); -	len_ptr = (ulong *)data; +		if (fit_image_get_os (images.fit_hdr_os, +					images.fit_noffset_os, &os)) { +			puts ("Can't get image OS!\n"); +			show_boot_progress (-111); +			return 1; +		} -#if defined(__ARM__) -	if (hdr->ih_arch != IH_CPU_ARM) -#elif defined(__avr32__) -	if (hdr->ih_arch != IH_CPU_AVR32) -#elif defined(__bfin__) -	if (hdr->ih_arch != IH_CPU_BLACKFIN) -#elif defined(__I386__) -	if (hdr->ih_arch != IH_CPU_I386) -#elif defined(__M68K__) -	if (hdr->ih_arch != IH_CPU_M68K) -#elif defined(__microblaze__) -	if (hdr->ih_arch != IH_CPU_MICROBLAZE) -#elif defined(__mips__) -	if (hdr->ih_arch != IH_CPU_MIPS) -#elif defined(__nios__) -	if (hdr->ih_arch != IH_CPU_NIOS) -#elif defined(__nios2__) -	if (hdr->ih_arch != IH_CPU_NIOS2) -#elif defined(__PPC__) -	if (hdr->ih_arch != IH_CPU_PPC) -#elif defined(__sh__) -	if (hdr->ih_arch != IH_CPU_SH) -#else -# error Unknown CPU type -#endif -	{ -		printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch); -		show_boot_progress (-4); -		return 1; -	} -	show_boot_progress (5); +		image_end = fit_get_end (images.fit_hdr_os); -	switch (hdr->ih_type) { -	case IH_TYPE_STANDALONE: -		name = "Standalone Application"; -		/* A second argument overwrites the load address */ -		if (argc > 2) { -			hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16)); +		if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, +					&load_start)) { +			puts ("Can't get image load address!\n"); +			show_boot_progress (-112); +			return 1;  		}  		break; -	case IH_TYPE_KERNEL: -		name = "Kernel Image"; -		break; -	case IH_TYPE_MULTI: -		name = "Multi-File Image"; -		len  = ntohl(len_ptr[0]); -		/* OS kernel is always the first image */ -		data += 8; /* kernel_len + terminator */ -		for (i=1; len_ptr[i]; ++i) -			data += 4; -		break; -	default: printf ("Wrong Image Type for %s command\n", cmdtp->name); -		show_boot_progress (-5); +#endif +	default: +		puts ("ERROR: unknown image format type!\n");  		return 1;  	} -	show_boot_progress (6); + +	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();  #ifdef CONFIG_AMIGAONEG3SE @@ -316,138 +224,113 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	dcache_disable();  #endif -	switch (hdr->ih_comp) { +	switch (comp) {  	case IH_COMP_NONE: -		if(ntohl(hdr->ih_load) == addr) { -			printf ("   XIP %s ... ", name); +		if (load_start == (ulong)os_hdr) { +			printf ("   XIP %s ... ", type_name);  		} else { -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -			size_t l = len; -			void *to = (void *)ntohl(hdr->ih_load); -			void *from = (void *)data; +			printf ("   Loading %s ... ", type_name); -			printf ("   Loading %s ... ", name); +			memmove_wd ((void *)load_start, +				   (void *)os_data, os_len, CHUNKSZ); -			while (l > 0) { -				size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; -				WATCHDOG_RESET(); -				memmove (to, from, tail); -				to += tail; -				from += tail; -				l -= tail; -			} -#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ -			memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); -#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +			load_end = load_start + os_len; +			puts("OK\n");  		}  		break;  	case IH_COMP_GZIP: -		printf ("   Uncompressing %s ... ", name); -		if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, -			    (uchar *)data, &len) != 0) { -			puts ("GUNZIP ERROR - must RESET board to recover\n"); +		printf ("   Uncompressing %s ... ", type_name); +		if (gunzip ((void *)load_start, unc_len, +					(uchar *)os_data, &os_len) != 0) { +			puts ("GUNZIP: uncompress or overwrite error " +				"- must RESET board to recover\n");  			show_boot_progress (-6);  			do_reset (cmdtp, flag, argc, argv);  		} + +		load_end = load_start + os_len;  		break;  #ifdef CONFIG_BZIP2  	case IH_COMP_BZIP2: -		printf ("   Uncompressing %s ... ", name); +		printf ("   Uncompressing %s ... ", type_name);  		/*  		 * If we've got less than 4 MB of malloc() space,  		 * use slower decompression algorithm which requires  		 * at most 2300 KB of memory.  		 */ -		i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), -						&unc_len, (char *)data, len, -						CFG_MALLOC_LEN < (4096 * 1024), 0); +		int i = BZ2_bzBuffToBuffDecompress ((char*)load_start, +					&unc_len, (char *)os_data, os_len, +					CFG_MALLOC_LEN < (4096 * 1024), 0);  		if (i != BZ_OK) { -			printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); +			printf ("BUNZIP2: uncompress or overwrite error %d " +				"- must RESET board to recover\n", i);  			show_boot_progress (-6);  			do_reset (cmdtp, flag, argc, argv);  		} + +		load_end = load_start + unc_len;  		break;  #endif /* CONFIG_BZIP2 */  	default:  		if (iflag)  			enable_interrupts(); -		printf ("Unimplemented compression type %d\n", hdr->ih_comp); +		printf ("Unimplemented compression type %d\n", comp);  		show_boot_progress (-7);  		return 1;  	}  	puts ("OK\n"); +	debug ("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end);  	show_boot_progress (7); -	switch (hdr->ih_type) { -	case IH_TYPE_STANDALONE: -		if (iflag) -			enable_interrupts(); +	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); -		/* load (and uncompress), but don't start if "autostart" -		 * is set to "no" -		 */ -		if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) { -			char buf[32]; -			sprintf(buf, "%lX", len); -			setenv("filesize", buf); -			return 0; -		} -		appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep); -		(*appl)(argc-1, &argv[1]); -		return 0; -	case IH_TYPE_KERNEL: -	case IH_TYPE_MULTI: -		/* handled below */ -		break; -	default: -		if (iflag) -			enable_interrupts(); -		printf ("Can't boot image type %d\n", hdr->ih_type); -		show_boot_progress (-8); -		return 1; +		puts ("ERROR: image overwritten - must RESET the board to recover.\n"); +		show_boot_progress (-113); +		do_reset (cmdtp, flag, argc, argv);  	} +  	show_boot_progress (8); -	switch (hdr->ih_os) { +	lmb_reserve(&lmb, load_start, (load_end - load_start)); + +	switch (os) {  	default:			/* handled by (original) Linux case */  	case IH_OS_LINUX:  #ifdef CONFIG_SILENT_CONSOLE  	    fixup_silent_linux();  #endif -	    do_bootm_linux  (cmdtp, flag, argc, argv, -			     addr, len_ptr, verify); +	    do_bootm_linux (cmdtp, flag, argc, argv, &images);  	    break; +  	case IH_OS_NETBSD: -	    do_bootm_netbsd (cmdtp, flag, argc, argv, -			     addr, len_ptr, verify); +	    do_bootm_netbsd (cmdtp, flag, argc, argv, &images);  	    break;  #ifdef CONFIG_LYNXKDI  	case IH_OS_LYNXOS: -	    do_bootm_lynxkdi (cmdtp, flag, argc, argv, -			     addr, len_ptr, verify); +	    do_bootm_lynxkdi (cmdtp, flag, argc, argv, &images);  	    break;  #endif  	case IH_OS_RTEMS: -	    do_bootm_rtems (cmdtp, flag, argc, argv, -			     addr, len_ptr, verify); +	    do_bootm_rtems (cmdtp, flag, argc, argv, &images);  	    break;  #if defined(CONFIG_CMD_ELF)  	case IH_OS_VXWORKS: -	    do_bootm_vxworks (cmdtp, flag, argc, argv, -			      addr, len_ptr, verify); +	    do_bootm_vxworks (cmdtp, flag, argc, argv, &images);  	    break; +  	case IH_OS_QNX: -	    do_bootm_qnxelf (cmdtp, flag, argc, argv, -			      addr, len_ptr, verify); +	    do_bootm_qnxelf (cmdtp, flag, argc, argv, &images);  	    break;  #endif +  #ifdef CONFIG_ARTOS  	case IH_OS_ARTOS: -	    do_bootm_artos  (cmdtp, flag, argc, argv, -			     addr, len_ptr, verify); +	    do_bootm_artos (cmdtp, flag, argc, argv, &images);  	    break;  #endif  	} @@ -455,94 +338,94 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	show_boot_progress (-9);  #ifdef DEBUG  	puts ("\n## Control returned to monitor - resetting...\n"); -	do_reset (cmdtp, flag, argc, argv); +	if (images.autostart) +		do_reset (cmdtp, flag, argc, argv);  #endif +	if (!images.autostart && iflag) +		enable_interrupts(); +  	return 1;  } -U_BOOT_CMD( - 	bootm,	CFG_MAXARGS,	1,	do_bootm, - 	"bootm   - boot application image from memory\n", - 	"[addr [arg ...]]\n    - boot application image stored in memory\n" - 	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" - 	"\t'arg' can be the address of an initrd image\n" -#if defined(CONFIG_OF_FLAT_TREE) || 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 -); - -#ifdef CONFIG_SILENT_CONSOLE -static void -fixup_silent_linux () +/** + * image_get_kernel - verify legacy format kernel image + * @img_addr: in RAM address of the legacy format image to be verified + * @verify: data CRC verification flag + * + * image_get_kernel() verifies legacy image integrity and returns pointer to + * legacy image header if image verification was completed successfully. + * + * returns: + *     pointer to a legacy image header if valid image was found + *     otherwise return NULL + */ +static image_header_t *image_get_kernel (ulong img_addr, int verify)  { -	char buf[256], *start, *end; -	char *cmdline = getenv ("bootargs"); +	image_header_t *hdr = (image_header_t *)img_addr; -	/* Only fix cmdline when requested */ -	if (!(gd->flags & GD_FLG_SILENT)) -		return; +	if (!image_check_magic(hdr)) { +		puts ("Bad Magic Number\n"); +		show_boot_progress (-1); +		return NULL; +	} +	show_boot_progress (2); -	debug ("before silent fix-up: %s\n", cmdline); -	if (cmdline) { -		if ((start = strstr (cmdline, "console=")) != NULL) { -			end = strchr (start, ' '); -			strncpy (buf, cmdline, (start - cmdline + 8)); -			if (end) -				strcpy (buf + (start - cmdline + 8), end); -			else -				buf[start - cmdline + 8] = '\0'; -		} else { -			strcpy (buf, cmdline); -			strcat (buf, " console="); +	if (!image_check_hcrc (hdr)) { +		puts ("Bad Header Checksum\n"); +		show_boot_progress (-2); +		return NULL; +	} + +	show_boot_progress (3); +	image_print_contents (hdr); + +	if (verify) { +		puts ("   Verifying Checksum ... "); +		if (!image_check_dcrc (hdr)) { +			printf ("Bad Data CRC\n"); +			show_boot_progress (-3); +			return NULL;  		} -	} else { -		strcpy (buf, "console="); +		puts ("OK\n");  	} +	show_boot_progress (4); -	setenv ("bootargs", buf); -	debug ("after silent fix-up: %s\n", buf); +	if (!image_check_target_arch (hdr)) { +		printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr)); +		show_boot_progress (-4); +		return NULL; +	} +	return hdr;  } -#endif /* CONFIG_SILENT_CONSOLE */ -#ifdef CONFIG_PPC -static void  __attribute__((noinline)) -do_bootm_linux (cmd_tbl_t *cmdtp, int flag, -		int	argc, char *argv[], -		ulong	addr, -		ulong	*len_ptr, -		int	verify) +/** + * fit_check_kernel - verify FIT format kernel subimage + * @fit_hdr: pointer to the FIT image header + * os_noffset: kernel subimage node offset within FIT image + * @verify: data CRC verification flag + * + * fit_check_kernel() verifies integrity of the kernel subimage and from + * specified FIT image. + * + * returns: + *     1, on success + *     0, on failure + */ +#if defined (CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify)  { -	ulong	sp; -	ulong	len, checksum; -	ulong	initrd_start, initrd_end; -	ulong	cmd_start, cmd_end; -	ulong	initrd_high; -	ulong	data; -	int	initrd_copy_to_ram = 1; -	char    *cmdline; -	char	*s; -	bd_t	*kbd; -	void	(*kernel)(bd_t *, ulong, ulong, ulong, ulong); -	image_header_t *hdr = &header; -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) -	char	*of_flat_tree = NULL; -	ulong	of_data = 0; -#endif +	fit_image_print (fit, os_noffset, "   "); -	if ((s = getenv ("initrd_high")) != NULL) { -		/* a value of "no" or a similar string will act like 0, -		 * turning the "load high" feature off. This is intentional. -		 */ -		initrd_high = simple_strtoul(s, NULL, 16); -		if (initrd_high == ~0) -			initrd_copy_to_ram = 0; -	} else {	/* not set, no restrictions to load high */ -		initrd_high = ~0; +	if (verify) { +		puts ("   Verifying Hash Integrity ... "); +		if (!fit_image_check_hashes (fit, os_noffset)) { +			puts ("Bad Data Hash\n"); +			show_boot_progress (-104); +			return 0; +		} +		puts ("OK\n");  	} +	show_boot_progress (105);  #ifdef CONFIG_LOGBUFFER  #ifndef CONFIG_ALT_LB_ADDR @@ -555,525 +438,445 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  	debug ("## Logbuffer at 0x%08lX ", CONFIG_ALT_LB_ADDR);  #endif  #endif +	if (!fit_image_check_target_arch (fit, os_noffset)) { +		puts ("Unsupported Architecture\n"); +		show_boot_progress (-105); +		return 0; +	} -	/* -	 * Booting a (Linux) kernel image -	 * -	 * Allocate space for command line and board info - the -	 * address should be as high as possible within the reach of -	 * the kernel (see CFG_BOOTMAPSZ settings), but in unused -	 * memory, which means far enough below the current stack -	 * pointer. -	 */ - -	asm( "mr %0,1": "=r"(sp) : ); - -	debug ("## Current stack ends at 0x%08lX ", sp); - -	sp -= 2048;		/* just to be sure */ -	if (sp > CFG_BOOTMAPSZ) -		sp = CFG_BOOTMAPSZ; -	sp &= ~0xF; - -	debug ("=> set upper limit to 0x%08lX\n", sp); - -	cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); -	kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); - -	if ((s = getenv("bootargs")) == NULL) -		s = ""; - -	strcpy (cmdline, s); - -	cmd_start    = (ulong)&cmdline[0]; -	cmd_end      = cmd_start + strlen(cmdline); - -	*kbd = *(gd->bd); +	show_boot_progress (106); +	if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) { +		puts ("Not a kernel image\n"); +		show_boot_progress (-106); +		return 0; +	} -#ifdef	DEBUG -	printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); +	show_boot_progress (107); +	return 1; +} +#endif /* CONFIG_FIT */ -	do_bdinfo (NULL, 0, 0, NULL); +/** + * boot_get_kernel - find kernel image + * @os_data: pointer to a ulong variable, will hold os data start address + * @os_len: pointer to a ulong variable, will hold os data length + * + * boot_get_kernel() tries to find a kernel image, verifies its integrity + * and locates kernel data. + * + * returns: + *     pointer to image header if valid image was found, plus kernel start + *     address and length, otherwise NULL + */ +static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +		bootm_headers_t *images, ulong *os_data, ulong *os_len) +{ +	image_header_t	*hdr; +	ulong		img_addr; +#if defined(CONFIG_FIT) +	void		*fit_hdr; +	const char	*fit_uname_config = NULL; +	const char	*fit_uname_kernel = NULL; +	const void	*data; +	size_t		len; +	int		cfg_noffset; +	int		os_noffset;  #endif -	if ((s = getenv ("clocks_in_mhz")) != NULL) { -		/* convert all clock information to MHz */ -		kbd->bi_intfreq /= 1000000L; -		kbd->bi_busfreq /= 1000000L; -#if defined(CONFIG_MPC8220) -	kbd->bi_inpfreq /= 1000000L; -	kbd->bi_pcifreq /= 1000000L; -	kbd->bi_pevfreq /= 1000000L; -	kbd->bi_flbfreq /= 1000000L; -	kbd->bi_vcofreq /= 1000000L; -#endif -#if defined(CONFIG_CPM2) -		kbd->bi_cpmfreq /= 1000000L; -		kbd->bi_brgfreq /= 1000000L; -		kbd->bi_sccfreq /= 1000000L; -		kbd->bi_vco     /= 1000000L; +	/* find out kernel image address */ +	if (argc < 2) { +		img_addr = load_addr; +		debug ("*  kernel: default image load address = 0x%08lx\n", +				load_addr); +#if defined(CONFIG_FIT) +	} else if (fit_parse_conf (argv[1], load_addr, &img_addr, +							&fit_uname_config)) { +		debug ("*  kernel: config '%s' from image at 0x%08lx\n", +				fit_uname_config, img_addr); +	} else if (fit_parse_subimage (argv[1], load_addr, &img_addr, +							&fit_uname_kernel)) { +		debug ("*  kernel: subimage '%s' from image at 0x%08lx\n", +				fit_uname_kernel, img_addr);  #endif -#if defined(CONFIG_MPC5xxx) -		kbd->bi_ipbfreq /= 1000000L; -		kbd->bi_pcifreq /= 1000000L; -#endif /* CONFIG_MPC5xxx */ +	} else { +		img_addr = simple_strtoul(argv[1], NULL, 16); +		debug ("*  kernel: cmdline image address = 0x%08lx\n", img_addr);  	} -	kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong)) ntohl(hdr->ih_ep); - -	/* -	 * Check if there is an initrd image -	 */ - -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) -	/* Look for a '-' which indicates to ignore the ramdisk argument */ -	if (argc >= 3 && strcmp(argv[2], "-") ==  0) { -			debug ("Skipping initrd\n"); -			len = data = 0; -		} -	else -#endif -	if (argc >= 3) { -		debug ("Not skipping initrd\n"); -		show_boot_progress (9); - -		addr = simple_strtoul(argv[2], NULL, 16); +	show_boot_progress (1); -		printf ("## Loading RAMDisk Image at %08lx ...\n", addr); +	/* copy from dataflash if needed */ +	img_addr = genimg_get_image (img_addr); -		/* Copy header so we can blank CRC field for re-calculation */ -		memmove (&header, (char *)addr, sizeof(image_header_t)); +	/* check image type, for FIT images get FIT kernel node */ +	*os_data = *os_len = 0; +	switch (genimg_get_format ((void *)img_addr)) { +	case IMAGE_FORMAT_LEGACY: +		printf ("## Booting kernel from Legacy Image at %08lx ...\n", +				img_addr); +		hdr = image_get_kernel (img_addr, images->verify); +		if (!hdr) +			return NULL; +		show_boot_progress (5); -		if (ntohl(hdr->ih_magic)  != IH_MAGIC) { -			puts ("Bad Magic Number\n"); -			show_boot_progress (-10); -			do_reset (cmdtp, flag, argc, argv); +		/* get os_data and os_len */ +		switch (image_get_type (hdr)) { +		case IH_TYPE_KERNEL: +			*os_data = image_get_data (hdr); +			*os_len = image_get_data_size (hdr); +			break; +		case IH_TYPE_MULTI: +			image_multi_getimg (hdr, 0, os_data, os_len); +			break; +		default: +			printf ("Wrong Image Type for %s command\n", cmdtp->name); +			show_boot_progress (-5); +			return NULL;  		} +		images->legacy_hdr_os = hdr; +		images->legacy_hdr_valid = 1; -		data = (ulong)&header; -		len  = sizeof(image_header_t); - -		checksum = ntohl(hdr->ih_hcrc); -		hdr->ih_hcrc = 0; +		show_boot_progress (6); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (void *)img_addr; +		printf ("## Booting kernel from FIT Image at %08lx ...\n", +				img_addr); -		if (crc32 (0, (uchar *)data, len) != checksum) { -			puts ("Bad Header Checksum\n"); -			show_boot_progress (-11); -			do_reset (cmdtp, flag, argc, argv); +		if (!fit_check_format (fit_hdr)) { +			puts ("Bad FIT kernel image format!\n"); +			show_boot_progress (-100); +			return NULL;  		} +		show_boot_progress (100); -		show_boot_progress (10); - -		print_image_hdr (hdr); - -		data = addr + sizeof(image_header_t); -		len  = ntohl(hdr->ih_size); - -		if (verify) { -			ulong csum = 0; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -			ulong cdata = data, edata = cdata + len; -#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - -			puts ("   Verifying Checksum ... "); - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - -			while (cdata < edata) { -				ulong chunk = edata - cdata; - -				if (chunk > CHUNKSZ) -					chunk = CHUNKSZ; -				csum = crc32 (csum, (uchar *)cdata, chunk); -				cdata += chunk; - -				WATCHDOG_RESET(); +		if (!fit_uname_kernel) { +			/* +			 * no kernel image node unit name, try to get config +			 * node first. If config unit node name is NULL +			 * fit_conf_get_node() will try to find default config node +			 */ +			show_boot_progress (101); +			cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); +			if (cfg_noffset < 0) { +				show_boot_progress (-101); +				return NULL;  			} -#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ -			csum = crc32 (0, (uchar *)data, len); -#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +			/* save configuration uname provided in the first +			 * bootm argument +			 */ +			images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL); +			printf ("   Using '%s' configuration\n", images->fit_uname_cfg); +			show_boot_progress (103); -			if (csum != ntohl(hdr->ih_dcrc)) { -				puts ("Bad Data CRC\n"); -				show_boot_progress (-12); -				do_reset (cmdtp, flag, argc, argv); -			} -			puts ("OK\n"); +			os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset); +			fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); +		} else { +			/* get kernel component image node offset */ +			show_boot_progress (102); +			os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel);  		} - -		show_boot_progress (11); - -		if ((hdr->ih_os   != IH_OS_LINUX)	|| -		    (hdr->ih_arch != IH_CPU_PPC)	|| -		    (hdr->ih_type != IH_TYPE_RAMDISK)	) { -			puts ("No Linux PPC Ramdisk Image\n"); -			show_boot_progress (-13); -			do_reset (cmdtp, flag, argc, argv); +		if (os_noffset < 0) { +			show_boot_progress (-103); +			return NULL;  		} -		/* -		 * Now check if we have a multifile image -		 */ -	} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { -		u_long tail    = ntohl(len_ptr[0]) % 4; -		int i; +		printf ("   Trying '%s' kernel subimage\n", fit_uname_kernel); -		show_boot_progress (13); +		show_boot_progress (104); +		if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) +			return NULL; -		/* skip kernel length and terminator */ -		data = (ulong)(&len_ptr[2]); -		/* skip any additional image length fields */ -		for (i=1; len_ptr[i]; ++i) -			data += 4; -		/* add kernel length, and align */ -		data += ntohl(len_ptr[0]); -		if (tail) { -			data += 4 - tail; +		/* get kernel image data address and length */ +		if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) { +			puts ("Could not find kernel subimage data!\n"); +			show_boot_progress (-107); +			return NULL;  		} +		show_boot_progress (108); -		len   = ntohl(len_ptr[1]); +		*os_len = len; +		*os_data = (ulong)data; +		images->fit_hdr_os = fit_hdr; +		images->fit_uname_os = fit_uname_kernel; +		images->fit_noffset_os = os_noffset; +		break; +#endif +	default: +		printf ("Wrong Image Format for %s command\n", cmdtp->name); +		show_boot_progress (-108); +		return NULL; +	} -	} else { -		/* -		 * no initrd image -		 */ -		show_boot_progress (14); +	debug ("   kernel data at 0x%08lx, len = 0x%08lx (%d)\n", +			*os_data, *os_len, *os_len); -		len = data = 0; -	} +	return (void *)img_addr; +} -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) -	if(argc > 3) { -		of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); -		hdr = (image_header_t *)of_flat_tree; -#if defined(CONFIG_OF_FLAT_TREE) -		if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { -#else -		if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { +U_BOOT_CMD( +	bootm,	CFG_MAXARGS,	1,	do_bootm, +	"bootm   - boot application image from memory\n", +	"[addr [arg ...]]\n    - boot application image stored in memory\n" +	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" +	"\t'arg' can be the address of an initrd image\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 -#ifndef CFG_NO_FLASH -			if (addr2info((ulong)of_flat_tree) != NULL) -				of_data = (ulong)of_flat_tree; +#if defined(CONFIG_FIT) +	"\t\nFor the new multi component uImage format (FIT) addresses\n" +	"\tmust be extened to include component or configuration unit name:\n" +	"\taddr:<subimg_uname> - direct component image specification\n" +	"\taddr#<conf_uname>   - configuration specification\n" +	"\tUse iminfo command to get the list of existing component\n" +	"\timages and configurations.\n"  #endif -		} else if (ntohl(hdr->ih_magic) == IH_MAGIC) { -			printf("## Flat Device Tree at %08lX\n", hdr); -			print_image_hdr(hdr); - -			if ((ntohl(hdr->ih_load) <  ((unsigned long)hdr + ntohl(hdr->ih_size) + sizeof(hdr))) && -			   ((ntohl(hdr->ih_load) + ntohl(hdr->ih_size)) > (unsigned long)hdr)) { -				puts ("ERROR: fdt overwritten - " -					"must RESET the board to recover.\n"); -				do_reset (cmdtp, flag, argc, argv); -			} +); -			puts ("   Verifying Checksum ... "); -			memmove (&header, (char *)hdr, sizeof(image_header_t)); -			checksum = ntohl(header.ih_hcrc); -			header.ih_hcrc = 0; +/*******************************************************************/ +/* bootd - boot default image */ +/*******************************************************************/ +#if defined(CONFIG_CMD_BOOTD) +int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	int rcode = 0; -			if(checksum != crc32(0, (uchar *)&header, sizeof(image_header_t))) { -				puts ("ERROR: fdt header checksum invalid - " -					"must RESET the board to recover.\n"); -				do_reset (cmdtp, flag, argc, argv); -			} +#ifndef CFG_HUSH_PARSER +	if (run_command (getenv ("bootcmd"), flag) < 0) +		rcode = 1; +#else +	if (parse_string_outer (getenv ("bootcmd"), +			FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) +		rcode = 1; +#endif +	return rcode; +} -			checksum = ntohl(hdr->ih_dcrc); -			addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t)); +U_BOOT_CMD( +	boot,	1,	1,	do_bootd, +	"boot    - boot default, i.e., run 'bootcmd'\n", +	NULL +); -			if(checksum != crc32(0, (uchar *)addr, ntohl(hdr->ih_size))) { -				puts ("ERROR: fdt checksum invalid - " -					"must RESET the board to recover.\n"); -				do_reset (cmdtp, flag, argc, argv); -			} -			puts ("OK\n"); +/* keep old command name "bootd" for backward compatibility */ +U_BOOT_CMD( +	bootd, 1,	1,	do_bootd, +	"bootd   - boot default, i.e., run 'bootcmd'\n", +	NULL +); -			if (ntohl(hdr->ih_type) != IH_TYPE_FLATDT) { -				puts ("ERROR: uImage is not a fdt - " -					"must RESET the board to recover.\n"); -				do_reset (cmdtp, flag, argc, argv); -			} -			if (ntohl(hdr->ih_comp) != IH_COMP_NONE) { -				puts ("ERROR: uImage is compressed - " -					"must RESET the board to recover.\n"); -				do_reset (cmdtp, flag, argc, argv); -			} -#if defined(CONFIG_OF_FLAT_TREE) -			if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { -#else -			if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {  #endif -				puts ("ERROR: uImage data is not a fdt - " -					"must RESET the board to recover.\n"); -				do_reset (cmdtp, flag, argc, argv); -			} -			memmove((void *)ntohl(hdr->ih_load), -		       		(void *)(of_flat_tree + sizeof(image_header_t)), -				ntohl(hdr->ih_size)); -			of_flat_tree = (char *)ntohl(hdr->ih_load); -		} else { -			puts ("Did not find a flat Flat Device Tree.\n" -				"Must RESET the board to recover.\n"); -			do_reset (cmdtp, flag, argc, argv); -		} -		printf ("   Booting using the fdt at 0x%x\n", -				of_flat_tree); -	} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) { -		u_long tail    = ntohl(len_ptr[0]) % 4; -		int i; -		/* skip kernel length, initrd length, and terminator */ -		of_flat_tree = (char *)(&len_ptr[3]); -		/* skip any additional image length fields */ -		for (i=2; len_ptr[i]; ++i) -			of_flat_tree += 4; -		/* add kernel length, and align */ -		of_flat_tree += ntohl(len_ptr[0]); -		if (tail) { -			of_flat_tree += 4 - tail; +/*******************************************************************/ +/* iminfo - print header info for a requested image */ +/*******************************************************************/ +#if defined(CONFIG_CMD_IMI) +int do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	int	arg; +	ulong	addr; +	int	rcode = 0; + +	if (argc < 2) { +		return image_info (load_addr); +	} + +	for (arg = 1; arg < argc; ++arg) { +		addr = simple_strtoul (argv[arg], NULL, 16); +		if (image_info (addr) != 0) +			rcode = 1; +	} +	return rcode; +} + +static int image_info (ulong addr) +{ +	void *hdr = (void *)addr; + +	printf ("\n## Checking Image at %08lx ...\n", addr); + +	switch (genimg_get_format (hdr)) { +	case IMAGE_FORMAT_LEGACY: +		puts ("   Legacy image found\n"); +		if (!image_check_magic (hdr)) { +			puts ("   Bad Magic Number\n"); +			return 1;  		} -		/* add initrd length, and align */ -		tail = ntohl(len_ptr[1]) % 4; -		of_flat_tree += ntohl(len_ptr[1]); -		if (tail) { -			of_flat_tree += 4 - tail; +		if (!image_check_hcrc (hdr)) { +			puts ("   Bad Header Checksum\n"); +			return 1;  		} -#ifndef CFG_NO_FLASH -		/* move the blob if it is in flash (set of_data to !null) */ -		if (addr2info ((ulong)of_flat_tree) != NULL) -			of_data = (ulong)of_flat_tree; -#endif +		image_print_contents (hdr); +		puts ("   Verifying Checksum ... "); +		if (!image_check_dcrc (hdr)) { +			puts ("   Bad Data CRC\n"); +			return 1; +		} +		puts ("OK\n"); +		return 0; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		puts ("   FIT image found\n"); -#if defined(CONFIG_OF_FLAT_TREE) -		if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) { -#else -		if (fdt_check_header (of_flat_tree) != 0) { -#endif -			puts ("ERROR: image is not a fdt - " -				"must RESET the board to recover.\n"); -			do_reset (cmdtp, flag, argc, argv); +		if (!fit_check_format (hdr)) { +			puts ("Bad FIT image format!\n"); +			return 1;  		} -#if defined(CONFIG_OF_FLAT_TREE) -		if (((struct boot_param_header *)of_flat_tree)->totalsize != -			ntohl (len_ptr[2])) { -#else -		if (be32_to_cpu (fdt_totalsize (of_flat_tree)) != -			ntohl(len_ptr[2])) { +		fit_print_contents (hdr); +		return 0;  #endif -			puts ("ERROR: fdt size != image size - " -				"must RESET the board to recover.\n"); -			do_reset (cmdtp, flag, argc, argv); -		} +	default: +		puts ("Unknown image format!\n"); +		break;  	} + +	return 1; +} + +U_BOOT_CMD( +	iminfo,	CFG_MAXARGS,	1,	do_iminfo, +	"iminfo  - print header information for application image\n", +	"addr [addr ...]\n" +	"    - print header information for application image starting at\n" +	"      address 'addr' in memory; this includes verification of the\n" +	"      image contents (magic number, header and payload checksums)\n" +);  #endif -	if (!data) { -		debug ("No initrd\n"); -	} -	if (data) { -	    if (!initrd_copy_to_ram) {	/* zero-copy ramdisk support */ -		initrd_start = data; -		initrd_end = initrd_start + len; -	    } else { -		initrd_start  = (ulong)kbd - len; -		initrd_start &= ~(4096 - 1);	/* align on page */ -		if (initrd_high) { -			ulong nsp; +/*******************************************************************/ +/* imls - list all images found in flash */ +/*******************************************************************/ +#if defined(CONFIG_CMD_IMLS) +int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	flash_info_t *info; +	int i, j; +	void *hdr; + +	for (i = 0, info = &flash_info[0]; +		i < CFG_MAX_FLASH_BANKS; ++i, ++info) { + +		if (info->flash_id == FLASH_UNKNOWN) +			goto next_bank; +		for (j = 0; j < info->sector_count; ++j) { -			/* -			 * the inital ramdisk does not need to be within -			 * CFG_BOOTMAPSZ as it is not accessed until after -			 * the mm system is initialised. -			 * -			 * do the stack bottom calculation again and see if -			 * the initrd will fit just below the monitor stack -			 * bottom without overwriting the area allocated -			 * above for command line args and board info. -			 */ -			asm( "mr %0,1": "=r"(nsp) : ); -			nsp -= 2048;		/* just to be sure */ -			nsp &= ~0xF; -			if (nsp > initrd_high)	/* limit as specified */ -				nsp = initrd_high; -			nsp -= len; -			nsp &= ~(4096 - 1);	/* align on page */ -			if (nsp >= sp) -				initrd_start = nsp; -		} +			hdr = (void *)info->start[j]; +			if (!hdr) +				goto next_sector; -		show_boot_progress (12); +			switch (genimg_get_format (hdr)) { +			case IMAGE_FORMAT_LEGACY: +				if (!image_check_hcrc (hdr)) +					goto next_sector; -		debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", -			data, data + len - 1, len, len); +				printf ("Legacy Image at %08lX:\n", (ulong)hdr); +				image_print_contents (hdr); -		initrd_end    = initrd_start + len; -		printf ("   Loading Ramdisk to %08lx, end %08lx ... ", -			initrd_start, initrd_end); -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -		{ -			size_t l = len; -			void *to = (void *)initrd_start; -			void *from = (void *)data; +				puts ("   Verifying Checksum ... "); +				if (!image_check_dcrc (hdr)) { +					puts ("Bad Data CRC\n"); +				} else { +					puts ("OK\n"); +				} +				break; +#if defined(CONFIG_FIT) +			case IMAGE_FORMAT_FIT: +				if (!fit_check_format (hdr)) +					goto next_sector; -			while (l > 0) { -				size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; -				WATCHDOG_RESET(); -				memmove (to, from, tail); -				to += tail; -				from += tail; -				l -= tail; +				printf ("FIT Image at %08lX:\n", (ulong)hdr); +				fit_print_contents (hdr); +				break; +#endif +			default: +				goto next_sector;  			} + +next_sector:		;  		} -#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ -		memmove ((void *)initrd_start, (void *)data, len); -#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ -		puts ("OK\n"); -	    } -	} else { -		initrd_start = 0; -		initrd_end = 0; +next_bank:	;  	} -#if defined(CONFIG_OF_LIBFDT) +	return (0); +} -#ifdef CFG_BOOTMAPSZ -	/* -	 * The blob must be within CFG_BOOTMAPSZ, -	 * so we flag it to be copied if it is not. -	 */ -	if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) -		of_data = (ulong)of_flat_tree; +U_BOOT_CMD( +	imls,	1,		1,	do_imls, +	"imls    - list all images found in flash\n", +	"\n" +	"    - Prints information about all images found at sector\n" +	"      boundaries in flash.\n" +);  #endif -	/* move of_flat_tree if needed */ -	if (of_data) { -		int err; -		ulong of_start, of_len; - -		of_len = be32_to_cpu(fdt_totalsize(of_data)); +/*******************************************************************/ +/* helper routines */ +/*******************************************************************/ +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux () +{ +	char buf[256], *start, *end; +	char *cmdline = getenv ("bootargs"); -		/* position on a 4K boundary before the kbd */ -		of_start  = (ulong)kbd - of_len; -		of_start &= ~(4096 - 1);	/* align on page */ -		debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", -			of_data, of_data + of_len - 1, of_len, of_len); +	/* Only fix cmdline when requested */ +	if (!(gd->flags & GD_FLG_SILENT)) +		return; -		of_flat_tree = (char *)of_start; -		printf ("   Loading Device Tree to %08lx, end %08lx ... ", -			of_start, of_start + of_len - 1); -		err = fdt_open_into((void *)of_data, (void *)of_start, of_len); -		if (err != 0) { -			puts ("ERROR: fdt move failed - " -				"must RESET the board to recover.\n"); -			do_reset (cmdtp, flag, argc, argv); -		} -		puts ("OK\n"); -	} -	/* -	 * Add the chosen node if it doesn't exist, add the env and bd_t -	 * if the user wants it (the logic is in the subroutines). -	 */ -	if (of_flat_tree) { -		if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { -			puts ("ERROR: /chosen node create failed - " -				"must RESET the board to recover.\n"); -			do_reset (cmdtp, flag, argc, argv); +	debug ("before silent fix-up: %s\n", cmdline); +	if (cmdline) { +		if ((start = strstr (cmdline, "console=")) != NULL) { +			end = strchr (start, ' '); +			strncpy (buf, cmdline, (start - cmdline + 8)); +			if (end) +				strcpy (buf + (start - cmdline + 8), end); +			else +				buf[start - cmdline + 8] = '\0'; +		} else { +			strcpy (buf, cmdline); +			strcat (buf, " console=");  		} -#ifdef CONFIG_OF_BOARD_SETUP -		/* Call the board-specific fixup routine */ -		ft_board_setup(of_flat_tree, gd->bd); -#endif +	} else { +		strcpy (buf, "console=");  	} -#endif /* CONFIG_OF_LIBFDT */ -#if defined(CONFIG_OF_FLAT_TREE) -#ifdef CFG_BOOTMAPSZ -	/* -	 * The blob must be within CFG_BOOTMAPSZ, -	 * so we flag it to be copied if it is not. -	 */ -	if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) -		of_data = (ulong)of_flat_tree; -#endif -	/* move of_flat_tree if needed */ -	if (of_data) { -		ulong of_start, of_len; -		of_len = ((struct boot_param_header *)of_data)->totalsize; - -		/* provide extra 8k pad */ -		of_start  = (ulong)kbd - of_len - 8192; -		of_start &= ~(4096 - 1);	/* align on page */ -		debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", -			of_data, of_data + of_len - 1, of_len, of_len); +	setenv ("bootargs", buf); +	debug ("after silent fix-up: %s\n", buf); +} +#endif /* CONFIG_SILENT_CONSOLE */ -		of_flat_tree = (char *)of_start; -		printf ("   Loading Device Tree to %08lx, end %08lx ... ", -			of_start, of_start + of_len - 1); -		memmove ((void *)of_start, (void *)of_data, of_len); -		puts ("OK\n"); -	} -	/* -	 * Create the /chosen node and modify the blob with board specific -	 * values as needed. -	 */ -	ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); -	/* ft_dump_blob(of_flat_tree); */ -#endif -	debug ("## Transferring control to Linux (at address %08lx) ...\n", -		(ulong)kernel); -	show_boot_progress (15); +/*******************************************************************/ +/* OS booting routines */ +/*******************************************************************/ -#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) -	unlock_ram_in_cache(); -#endif +static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, +			    int argc, char *argv[], +			    bootm_headers_t *images) +{ +	void (*loader)(bd_t *, image_header_t *, char *, char *); +	image_header_t *os_hdr, *hdr; +	ulong kernel_data, kernel_len; +	char *consdev; +	char *cmdline; -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) -	if (of_flat_tree) {	/* device tree; boot new style */ -		/* -		 * Linux Kernel Parameters (passing device tree): -		 *   r3: pointer to the fdt, followed by the board info data -		 *   r4: physical pointer to the kernel itself -		 *   r5: NULL -		 *   r6: NULL -		 *   r7: NULL -		 */ -		(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); -		/* does not return */ +#if defined(CONFIG_FIT) +	if (!images->legacy_hdr_valid) { +		fit_unsupported_reset ("NetBSD"); +		do_reset (cmdtp, flag, argc, argv);  	}  #endif -	/* -	 * Linux Kernel Parameters (passing board info data): -	 *   r3: ptr to board info data -	 *   r4: initrd_start or 0 if no initrd -	 *   r5: initrd_end - unused if r4 is 0 -	 *   r6: Start of command line string -	 *   r7: End   of command line string -	 */ -	(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); -	/* does not return */ -} -#endif /* CONFIG_PPC */ - -static void -do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, -		int	argc, char *argv[], -		ulong	addr, -		ulong	*len_ptr, -		int	verify) -{ -	image_header_t *hdr = &header; - -	void	(*loader)(bd_t *, image_header_t *, char *, char *); -	image_header_t *img_addr; -	char     *consdev; -	char     *cmdline; - +	hdr = images->legacy_hdr_os;  	/*  	 * Booting a (NetBSD) kernel image @@ -1086,11 +889,12 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,  	 * line, the name of the console device, and (optionally) the  	 * address of the original image header.  	 */ - -	img_addr = 0; -	if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) -		img_addr = (image_header_t *) addr; - +	os_hdr = NULL; +	if (image_check_type (hdr, IH_TYPE_MULTI)) { +		image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); +		if (kernel_len) +			os_hdr = hdr; +	}  	consdev = "";  #if   defined (CONFIG_8xx_CONS_SMC1) @@ -1107,21 +911,21 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,  		ulong len;  		int   i; -		for (i=2, len=0 ; i<argc ; i+=1) +		for (i = 2, len = 0; i < argc; i += 1)  			len += strlen (argv[i]) + 1;  		cmdline = malloc (len); -		for (i=2, len=0 ; i<argc ; i+=1) { +		for (i = 2, len = 0; i < argc; i += 1) {  			if (i > 2)  				cmdline[len++] = ' ';  			strcpy (&cmdline[len], argv[i]);  			len += strlen (argv[i]);  		} -	} else if ((cmdline = getenv("bootargs")) == NULL) { +	} else if ((cmdline = getenv ("bootargs")) == NULL) {  		cmdline = "";  	} -	loader = (void (*)(bd_t *, image_header_t *, char *, char *)) ntohl(hdr->ih_ep); +	loader = (void (*)(bd_t *, image_header_t *, char *, char *))image_get_ep (hdr);  	printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",  		(ulong)loader); @@ -1135,20 +939,101 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,  	 *   r5: console device  	 *   r6: boot args string  	 */ -	(*loader) (gd->bd, img_addr, consdev, cmdline); +	(*loader) (gd->bd, os_hdr, consdev, cmdline);  } -#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +#ifdef CONFIG_LYNXKDI +static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, +			     int argc, char *argv[], +			     bootm_headers_t *images) +{ +	image_header_t *hdr = images->legacy_hdr_os; -/* Function that returns a character from the environment */ -extern uchar (*env_get_char)(int); +#if defined(CONFIG_FIT) +	if (!images->legacy_hdr_valid) { +		fit_unsupported_reset ("Lynx"); +		do_reset (cmdtp, flag, argc, argv); +	} +#endif -static void -do_bootm_artos (cmd_tbl_t *cmdtp, int flag, -		int	argc, char *argv[], -		ulong	addr, -		ulong	*len_ptr, -		int	verify) +	lynxkdi_boot ((image_header_t *)hdr); +} +#endif /* CONFIG_LYNXKDI */ + +static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, +			   int argc, char *argv[], +			   bootm_headers_t *images) +{ +	image_header_t *hdr = images->legacy_hdr_os; +	void (*entry_point)(bd_t *); + +#if defined(CONFIG_FIT) +	if (!images->legacy_hdr_valid) { +		fit_unsupported_reset ("RTEMS"); +		do_reset (cmdtp, flag, argc, argv); +	} +#endif + +	entry_point = (void (*)(bd_t *))image_get_ep (hdr); + +	printf ("## Transferring control to RTEMS (at address %08lx) ...\n", +		(ulong)entry_point); + +	show_boot_progress (15); + +	/* +	 * RTEMS Parameters: +	 *   r3: ptr to board info data +	 */ +	(*entry_point)(gd->bd); +} + +#if defined(CONFIG_CMD_ELF) +static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, +			     int argc, char *argv[], +			     bootm_headers_t *images) +{ +	char str[80]; +	image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) +	if (hdr == NULL) { +		fit_unsupported_reset ("VxWorks"); +		do_reset (cmdtp, flag, argc, argv); +	} +#endif + +	sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ +	setenv("loadaddr", str); +	do_bootvx(cmdtp, 0, 0, NULL); +} + +static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, +			    int argc, char *argv[], +			    bootm_headers_t *images) +{ +	char *local_args[2]; +	char str[16]; +	image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) +	if (!images->legacy_hdr_valid) { +		fit_unsupported_reset ("QNX"); +		do_reset (cmdtp, flag, argc, argv); +	} +#endif + +	sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ +	local_args[0] = argv[0]; +	local_args[1] = str;	/* and provide it via the arguments */ +	do_bootelf(cmdtp, 0, 2, local_args); +} +#endif + +#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, +			   int argc, char *argv[], +			   bootm_headers_t *images)  {  	ulong top;  	char *s, *cmdline; @@ -1156,7 +1041,14 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag,  	int i, j, nxt, len, envno, envsz;  	bd_t *kbd;  	void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); -	image_header_t *hdr = &header; +	image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) +	if (!images->legacy_hdr_valid) { +		fit_unsupported_reset ("ARTOS"); +		do_reset (cmdtp, flag, argc, argv); +	} +#endif  	/*  	 * Booting an ARTOS kernel image + application @@ -1177,27 +1069,27 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag,  	debug ("=> set upper limit to 0x%08lX\n", top);  	/* first check the artos specific boot args, then the linux args*/ -	if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL) +	if ((s = getenv( "abootargs")) == NULL && (s = getenv ("bootargs")) == NULL)  		s = "";  	/* get length of cmdline, and place it */ -	len = strlen(s); +	len = strlen (s);  	top = (top - (len + 1)) & ~0xF;  	cmdline = (char *)top;  	debug ("## cmdline at 0x%08lX ", top); -	strcpy(cmdline, s); +	strcpy (cmdline, s);  	/* copy bdinfo */ -	top = (top - sizeof(bd_t)) & ~0xF; +	top = (top - sizeof (bd_t)) & ~0xF;  	debug ("## bd at 0x%08lX ", top);  	kbd = (bd_t *)top; -	memcpy(kbd, gd->bd, sizeof(bd_t)); +	memcpy (kbd, gd->bd, sizeof (bd_t));  	/* first find number of env entries, and their size */  	envno = 0;  	envsz = 0; -	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { -		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) +	for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { +		for (nxt = i; env_get_char (nxt) != '\0'; ++nxt)  			;  		envno++;  		envsz += (nxt - i) + 1;	/* plus trailing zero */ @@ -1205,7 +1097,7 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag,  	envno++;	/* plus the terminating zero */  	debug ("## %u envvars total size %u ", envno, envsz); -	top = (top - sizeof(char **)*envno) & ~0xF; +	top = (top - sizeof (char **) * envno) & ~0xF;  	fwenv = (char **)top;  	debug ("## fwenv at 0x%08lX ", top); @@ -1214,428 +1106,17 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag,  	ss = fwenv;  	/* now copy them */ -	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { -		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) +	for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { +		for (nxt = i; env_get_char (nxt) != '\0'; ++nxt)  			;  		*ss++ = s;  		for (j = i; j < nxt; ++j) -			*s++ = env_get_char(j); +			*s++ = env_get_char (j);  		*s++ = '\0';  	}  	*ss++ = NULL;	/* terminate */ -	entry = (void (*)(bd_t *, char *, char **, ulong))ntohl(hdr->ih_ep); -	(*entry)(kbd, cmdline, fwenv, top); +	entry = (void (*)(bd_t *, char *, char **, ulong))image_get_ep (hdr); +	(*entry) (kbd, cmdline, fwenv, top);  }  #endif - - -#if defined(CONFIG_CMD_BOOTD) -int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ -	int rcode = 0; -#ifndef CFG_HUSH_PARSER -	if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1; -#else -	if (parse_string_outer(getenv("bootcmd"), -		FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1; -#endif -	return rcode; -} - -U_BOOT_CMD( - 	boot,	1,	1,	do_bootd, - 	"boot    - boot default, i.e., run 'bootcmd'\n", -	NULL -); - -/* keep old command name "bootd" for backward compatibility */ -U_BOOT_CMD( - 	bootd, 1,	1,	do_bootd, - 	"bootd   - boot default, i.e., run 'bootcmd'\n", -	NULL -); - -#endif - -#if defined(CONFIG_CMD_IMI) -int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ -	int	arg; -	ulong	addr; -	int     rcode=0; - -	if (argc < 2) { -		return image_info (load_addr); -	} - -	for (arg=1; arg <argc; ++arg) { -		addr = simple_strtoul(argv[arg], NULL, 16); -		if (image_info (addr) != 0) rcode = 1; -	} -	return rcode; -} - -static int image_info (ulong addr) -{ -	ulong	data, len, checksum; -	image_header_t *hdr = &header; - -	printf ("\n## Checking Image at %08lx ...\n", addr); - -	/* Copy header so we can blank CRC field for re-calculation */ -	memmove (&header, (char *)addr, sizeof(image_header_t)); - -	if (ntohl(hdr->ih_magic) != IH_MAGIC) { -		puts ("   Bad Magic Number\n"); -		return 1; -	} - -	data = (ulong)&header; -	len  = sizeof(image_header_t); - -	checksum = ntohl(hdr->ih_hcrc); -	hdr->ih_hcrc = 0; - -	if (crc32 (0, (uchar *)data, len) != checksum) { -		puts ("   Bad Header Checksum\n"); -		return 1; -	} - -	/* for multi-file images we need the data part, too */ -	print_image_hdr ((image_header_t *)addr); - -	data = addr + sizeof(image_header_t); -	len  = ntohl(hdr->ih_size); - -	puts ("   Verifying Checksum ... "); -	if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { -		puts ("   Bad Data CRC\n"); -		return 1; -	} -	puts ("OK\n"); -	return 0; -} - -U_BOOT_CMD( -	iminfo,	CFG_MAXARGS,	1,	do_iminfo, -	"iminfo  - print header information for application image\n", -	"addr [addr ...]\n" -	"    - print header information for application image starting at\n" -	"      address 'addr' in memory; this includes verification of the\n" -	"      image contents (magic number, header and payload checksums)\n" -); - -#endif - -#if defined(CONFIG_CMD_IMLS) -/*----------------------------------------------------------------------- - * List all images found in flash. - */ -int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ -	flash_info_t *info; -	int i, j; -	image_header_t *hdr; -	ulong data, len, checksum; - -	for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) { -		if (info->flash_id == FLASH_UNKNOWN) -			goto next_bank; -		for (j=0; j<info->sector_count; ++j) { - -			if (!(hdr=(image_header_t *)info->start[j]) || -			    (ntohl(hdr->ih_magic) != IH_MAGIC)) -				goto next_sector; - -			/* Copy header so we can blank CRC field for re-calculation */ -			memmove (&header, (char *)hdr, sizeof(image_header_t)); - -			checksum = ntohl(header.ih_hcrc); -			header.ih_hcrc = 0; - -			if (crc32 (0, (uchar *)&header, sizeof(image_header_t)) -			    != checksum) -				goto next_sector; - -			printf ("Image at %08lX:\n", (ulong)hdr); -			print_image_hdr( hdr ); - -			data = (ulong)hdr + sizeof(image_header_t); -			len  = ntohl(hdr->ih_size); - -			puts ("   Verifying Checksum ... "); -			if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { -				puts ("   Bad Data CRC\n"); -			} -			puts ("OK\n"); -next_sector:		; -		} -next_bank:	; -	} - -	return (0); -} - -U_BOOT_CMD( -	imls,	1,		1,	do_imls, -	"imls    - list all images found in flash\n", -	"\n" -	"    - Prints information about all images found at sector\n" -	"      boundaries in flash.\n" -); -#endif - -void -print_image_hdr (image_header_t *hdr) -{ -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) -	time_t timestamp = (time_t)ntohl(hdr->ih_time); -	struct rtc_time tm; -#endif - -	printf ("   Image Name:   %.*s\n", IH_NMLEN, hdr->ih_name); -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) -	to_tm (timestamp, &tm); -	printf ("   Created:      %4d-%02d-%02d  %2d:%02d:%02d UTC\n", -		tm.tm_year, tm.tm_mon, tm.tm_mday, -		tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif -	puts ("   Image Type:   "); print_type(hdr); -	printf ("\n   Data Size:    %d Bytes = ", ntohl(hdr->ih_size)); -	print_size (ntohl(hdr->ih_size), "\n"); -	printf ("   Load Address: %08x\n" -		"   Entry Point:  %08x\n", -		 ntohl(hdr->ih_load), ntohl(hdr->ih_ep)); - -	if (hdr->ih_type == IH_TYPE_MULTI) { -		int i; -		ulong len; -		ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); - -		puts ("   Contents:\n"); -		for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) { -			printf ("   Image %d: %8ld Bytes = ", i, len); -			print_size (len, "\n"); -		} -	} -} - - -static void -print_type (image_header_t *hdr) -{ -	char *os, *arch, *type, *comp; - -	switch (hdr->ih_os) { -	case IH_OS_INVALID:	os = "Invalid OS";		break; -	case IH_OS_NETBSD:	os = "NetBSD";			break; -	case IH_OS_LINUX:	os = "Linux";			break; -	case IH_OS_VXWORKS:	os = "VxWorks";			break; -	case IH_OS_QNX:		os = "QNX";			break; -	case IH_OS_U_BOOT:	os = "U-Boot";			break; -	case IH_OS_RTEMS:	os = "RTEMS";			break; -#ifdef CONFIG_ARTOS -	case IH_OS_ARTOS:	os = "ARTOS";			break; -#endif -#ifdef CONFIG_LYNXKDI -	case IH_OS_LYNXOS:	os = "LynxOS";			break; -#endif -	default:		os = "Unknown OS";		break; -	} - -	switch (hdr->ih_arch) { -	case IH_CPU_INVALID:	arch = "Invalid CPU";		break; -	case IH_CPU_ALPHA:	arch = "Alpha";			break; -	case IH_CPU_ARM:	arch = "ARM";			break; -	case IH_CPU_AVR32:	arch = "AVR32";			break; -	case IH_CPU_BLACKFIN:	arch = "Blackfin";		break; -	case IH_CPU_I386:	arch = "Intel x86";		break; -	case IH_CPU_IA64:	arch = "IA64";			break; -	case IH_CPU_M68K:	arch = "M68K"; 			break; -	case IH_CPU_MICROBLAZE:	arch = "Microblaze"; 		break; -	case IH_CPU_MIPS64:	arch = "MIPS 64 Bit";		break; -	case IH_CPU_MIPS:	arch = "MIPS";			break; -	case IH_CPU_NIOS2:	arch = "Nios-II";		break; -	case IH_CPU_NIOS:	arch = "Nios";			break; -	case IH_CPU_PPC:	arch = "PowerPC";		break; -	case IH_CPU_S390:	arch = "IBM S390";		break; -	case IH_CPU_SH:		arch = "SuperH";		break; -	case IH_CPU_SPARC64:	arch = "SPARC 64 Bit";		break; -	case IH_CPU_SPARC:	arch = "SPARC";			break; -	default:		arch = "Unknown Architecture";	break; -	} - -	switch (hdr->ih_type) { -	case IH_TYPE_INVALID:	type = "Invalid Image";		break; -	case IH_TYPE_STANDALONE:type = "Standalone Program";	break; -	case IH_TYPE_KERNEL:	type = "Kernel Image";		break; -	case IH_TYPE_RAMDISK:	type = "RAMDisk Image";		break; -	case IH_TYPE_MULTI:	type = "Multi-File Image";	break; -	case IH_TYPE_FIRMWARE:	type = "Firmware";		break; -	case IH_TYPE_SCRIPT:	type = "Script";		break; -	case IH_TYPE_FLATDT:	type = "Flat Device Tree";	break; -	default:		type = "Unknown Image";		break; -	} - -	switch (hdr->ih_comp) { -	case IH_COMP_NONE:	comp = "uncompressed";		break; -	case IH_COMP_GZIP:	comp = "gzip compressed";	break; -	case IH_COMP_BZIP2:	comp = "bzip2 compressed";	break; -	default:		comp = "unknown compression";	break; -	} - -	printf ("%s %s %s (%s)", arch, os, type, comp); -} - -#define	ZALLOC_ALIGNMENT	16 - -static void *zalloc(void *x, unsigned items, unsigned size) -{ -	void *p; - -	size *= items; -	size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); - -	p = malloc (size); - -	return (p); -} - -static void zfree(void *x, void *addr, unsigned nb) -{ -	free (addr); -} - -#define HEAD_CRC	2 -#define EXTRA_FIELD	4 -#define ORIG_NAME	8 -#define COMMENT		0x10 -#define RESERVED	0xe0 - -#define DEFLATED	8 - -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) -{ -	z_stream s; -	int r, i, flags; - -	/* skip header */ -	i = 10; -	flags = src[3]; -	if (src[2] != DEFLATED || (flags & RESERVED) != 0) { -		puts ("Error: Bad gzipped data\n"); -		return (-1); -	} -	if ((flags & EXTRA_FIELD) != 0) -		i = 12 + src[10] + (src[11] << 8); -	if ((flags & ORIG_NAME) != 0) -		while (src[i++] != 0) -			; -	if ((flags & COMMENT) != 0) -		while (src[i++] != 0) -			; -	if ((flags & HEAD_CRC) != 0) -		i += 2; -	if (i >= *lenp) { -		puts ("Error: gunzip out of data in header\n"); -		return (-1); -	} - -	s.zalloc = zalloc; -	s.zfree = zfree; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -	s.outcb = (cb_func)WATCHDOG_RESET; -#else -	s.outcb = Z_NULL; -#endif	/* CONFIG_HW_WATCHDOG */ - -	r = inflateInit2(&s, -MAX_WBITS); -	if (r != Z_OK) { -		printf ("Error: inflateInit2() returned %d\n", r); -		return (-1); -	} -	s.next_in = src + i; -	s.avail_in = *lenp - i; -	s.next_out = dst; -	s.avail_out = dstlen; -	r = inflate(&s, Z_FINISH); -	if (r != Z_OK && r != Z_STREAM_END) { -		printf ("Error: inflate() returned %d\n", r); -		return (-1); -	} -	*lenp = s.next_out - (unsigned char *) dst; -	inflateEnd(&s); - -	return (0); -} - -#ifdef CONFIG_BZIP2 -void bz_internal_error(int errcode) -{ -	printf ("BZIP2 internal error %d\n", errcode); -} -#endif /* CONFIG_BZIP2 */ - -static void -do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], -		ulong addr, ulong *len_ptr, int verify) -{ -	image_header_t *hdr = &header; -	void	(*entry_point)(bd_t *); - -	entry_point = (void (*)(bd_t *)) ntohl(hdr->ih_ep); - -	printf ("## Transferring control to RTEMS (at address %08lx) ...\n", -		(ulong)entry_point); - -	show_boot_progress (15); - -	/* -	 * RTEMS Parameters: -	 *   r3: ptr to board info data -	 */ - -	(*entry_point ) ( gd->bd ); -} - -#if defined(CONFIG_CMD_ELF) -static void -do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], -		  ulong addr, ulong *len_ptr, int verify) -{ -	image_header_t *hdr = &header; -	char str[80]; - -	sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ -	setenv("loadaddr", str); -	do_bootvx(cmdtp, 0, 0, NULL); -} - -static void -do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], -		 ulong addr, ulong *len_ptr, int verify) -{ -	image_header_t *hdr = &header; -	char *local_args[2]; -	char str[16]; - -	sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ -	local_args[0] = argv[0]; -	local_args[1] = str;	/* and provide it via the arguments */ -	do_bootelf(cmdtp, 0, 2, local_args); -} -#endif - -#ifdef CONFIG_LYNXKDI -static void -do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, -		 int	argc, char *argv[], -		 ulong	addr, -		 ulong	*len_ptr, -		 int	verify) -{ -	lynxkdi_boot( &header ); -} - -#endif /* CONFIG_LYNXKDI */ diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 3d717c039..83aba3744 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -205,6 +205,9 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	ulong offset = 0;  	image_header_t *hdr;  	int rcode = 0; +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif  	show_boot_progress (34);  	switch (argc) { @@ -261,21 +264,36 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	}  	show_boot_progress (38); -	hdr = (image_header_t *)addr; +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; -	if (hdr->ih_magic == IH_MAGIC) { +		image_print_contents (hdr); -		print_image_hdr (hdr); +		cnt = image_get_image_size (hdr); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			show_boot_progress (-130); +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		show_boot_progress (131); +		puts ("Fit image detected...\n"); -		cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); -		cnt -= SECTORSIZE; -	} else { -		puts ("\n** Bad Magic Number **\n"); +		cnt = fit_get_size (fit_hdr); +		break; +#endif +	default:  		show_boot_progress (-39); +		puts ("** Unknown image type\n");  		return 1;  	}  	show_boot_progress (39); +	cnt -= SECTORSIZE;  	if (doc_rw (doc_dev_desc + dev, 1, offset + SECTORSIZE, cnt,  		    NULL, (u_char *)(addr+SECTORSIZE))) {  		printf ("** Read error on %d\n", dev); @@ -284,6 +302,12 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	}  	show_boot_progress (40); +#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) +		fit_print_contents ((const void *)addr); +#endif +  	/* Loading ok, update default load address */  	load_addr = addr; diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 7349412c7..bf283702d 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -788,6 +788,9 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	int i,nrofblk;  	char *ep;  	int rcode = 0; +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif  	switch (argc) {  	case 1: @@ -835,14 +838,31 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  			printf("result%d: 0x%02X\n",i,pCMD->result[i]);  		return 1;  	} -	hdr = (image_header_t *)addr; -	if (ntohl(hdr->ih_magic)  != IH_MAGIC) { -		printf ("Bad Magic Number\n"); + +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; +		image_print_contents (hdr); + +		imsize = image_get_image_size (hdr); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		puts ("Fit image detected...\n"); + +		imsize = fit_get_size (fit_hdr); +		break; +#endif +	default: +		puts ("** Unknown image type\n");  		return 1;  	} -	print_image_hdr(hdr); -	imsize= ntohl(hdr->ih_size)+sizeof(image_header_t);  	nrofblk=imsize/512;  	if((imsize%512)>0)  		nrofblk++; @@ -858,23 +878,28 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	printf("OK %ld Bytes loaded.\n",imsize);  	flush_cache (addr, imsize); -	/* Loading ok, update default load address */ +#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) +		fit_print_contents ((const void *)addr); +#endif + +	/* Loading ok, update default load address */  	load_addr = addr; -	if(hdr->ih_type  == IH_TYPE_KERNEL) { -		/* Check if we should attempt an auto-start */ -		if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { -			char *local_args[2]; -			extern int do_bootm (cmd_tbl_t *, int, int, char *[]); -			local_args[0] = argv[0]; -			local_args[1] = NULL; +	/* Check if we should attempt an auto-start */ +	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { +		char *local_args[2]; +		extern int do_bootm (cmd_tbl_t *, int, int, char *[]); -			printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); +		local_args[0] = argv[0]; +		local_args[1] = NULL; -			do_bootm (cmdtp, 0, 1, local_args); -			rcode ++; -		} +		printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + +		do_bootm (cmdtp, 0, 1, local_args); +		rcode ++;  	}  	return rcode;  } diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index f55447ab1..9141dcce9 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -164,6 +164,10 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	char *devstr = getenv ("fpga");  	char *datastr = getenv ("fpgadata");  	int rc = FPGA_FAIL; +#if defined (CONFIG_FIT) +	const char *fit_uname = NULL; +	ulong fit_addr; +#endif  	if (devstr)  		dev = (int) simple_strtoul (devstr, NULL, 16); @@ -173,9 +177,22 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	switch (argc) {  	case 5:		/* fpga <op> <dev> <data> <datasize> */  		data_size = simple_strtoul (argv[4], NULL, 16); +  	case 4:		/* fpga <op> <dev> <data> */ -		fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); +#if defined(CONFIG_FIT) +		if (fit_parse_subimage (argv[3], (ulong)fpga_data, +					&fit_addr, &fit_uname)) { +			fpga_data = (void *)fit_addr; +			debug ("*  fpga: subimage '%s' from FIT image at 0x%08lx\n", +					fit_uname, fit_addr); +		} else +#endif +		{ +			fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); +			debug ("*  fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); +		}  		PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data); +  	case 3:		/* fpga <op> <dev | data addr> */  		dev = (int) simple_strtoul (argv[2], NULL, 16);  		PRINTF ("%s: device = %d\n", __FUNCTION__, dev); @@ -183,14 +200,29 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		if ((argc == 3) && (dev > fpga_count ())) {	/* must be buffer ptr */  			PRINTF ("%s: Assuming buffer pointer in arg 3\n",  				__FUNCTION__); -			fpga_data = (void *) dev; + +#if defined(CONFIG_FIT) +			if (fit_parse_subimage (argv[2], (ulong)fpga_data, +						&fit_addr, &fit_uname)) { +				fpga_data = (void *)fit_addr; +				debug ("*  fpga: subimage '%s' from FIT image at 0x%08lx\n", +						fit_uname, fit_addr); +			} else +#endif +			{ +				fpga_data = (void *) dev; +				debug ("*  fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); +			} +  			PRINTF ("%s: fpga_data = 0x%x\n",  				__FUNCTION__, (uint) fpga_data);  			dev = FPGA_INVALID_DEVICE;	/* reset device num */  		} +  	case 2:		/* fpga <op> */  		op = (int) fpga_get_op (argv[1]);  		break; +  	default:  		PRINTF ("%s: Too many or too few args (%d)\n",  			__FUNCTION__, argc); @@ -216,19 +248,61 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		break;  	case FPGA_LOADMK: -		{ -			image_header_t header; -			image_header_t *hdr = &header; -			ulong	data; +		switch (genimg_get_format (fpga_data)) { +		case IMAGE_FORMAT_LEGACY: +			{ +				image_header_t *hdr = (image_header_t *)fpga_data; +				ulong	data; -			memmove (&header, (char *)fpga_data, sizeof(image_header_t)); -			if (ntohl(hdr->ih_magic) != IH_MAGIC) { -				puts ("Bad Magic Number\n"); -				return 1; +				data = (ulong)image_get_data (hdr); +				data_size = image_get_data_size (hdr); +				rc = fpga_load (dev, (void *)data, data_size);  			} -			data = ((ulong)fpga_data + sizeof(image_header_t)); -			data_size  = ntohl(hdr->ih_size); -			rc = fpga_load (dev, (void *)data, data_size); +			break; +#if defined(CONFIG_FIT) +		case IMAGE_FORMAT_FIT: +			{ +				const void *fit_hdr = (const void *)fpga_data; +				int noffset; +				void *fit_data; + +				if (fit_uname == NULL) { +					puts ("No FIT subimage unit name\n"); +					return 1; +				} + +				if (!fit_check_format (fit_hdr)) { +					puts ("Bad FIT image format\n"); +					return 1; +				} + +				/* get fpga component image node offset */ +				noffset = fit_image_get_node (fit_hdr, fit_uname); +				if (noffset < 0) { +					printf ("Can't find '%s' FIT subimage\n", fit_uname); +					return 1; +				} + +				/* verify integrity */ +				if (!fit_image_check_hashes (fit_hdr, noffset)) { +					puts ("Bad Data Hash\n"); +					return 1; +				} + +				/* get fpga subimage data address and length */ +				if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) { +					puts ("Could not find fpga subimage data\n"); +					return 1; +				} + +				rc = fpga_load (dev, fit_data, data_size); +			} +			break; +#endif +		default: +			puts ("** Unknown image type\n"); +			rc = FPGA_FAIL; +			break;  		}  		break; @@ -283,4 +357,9 @@ U_BOOT_CMD (fpga, 6, 1, do_fpga,  	    "\tload\tLoad device from memory buffer\n"  	    "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"  	    "\tloadmk\tLoad device generated with mkimage\n" -	    "\tdump\tLoad device to memory buffer\n"); +	    "\tdump\tLoad device to memory buffer\n" +#if defined(CONFIG_FIT) +	    "\tFor loadmk operating on FIT format uImage address must include\n" +	    "\tsubimage unit name in the form of addr:<subimg_uname>\n" +#endif +); diff --git a/common/cmd_ide.c b/common/cmd_ide.c index c38be4f1a..8ace970c7 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -366,10 +366,13 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	char *boot_device = NULL;  	char *ep;  	int dev, part = 0; -	ulong addr, cnt, checksum; +	ulong addr, cnt;  	disk_partition_t info;  	image_header_t *hdr;  	int rcode = 0; +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif  	show_boot_progress (41);  	switch (argc) { @@ -446,29 +449,43 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	}  	show_boot_progress (48); -	hdr = (image_header_t *)addr; +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; -	if (ntohl(hdr->ih_magic) != IH_MAGIC) { -		printf("\n** Bad Magic Number **\n"); -		show_boot_progress (-49); -		return 1; -	} -	show_boot_progress (49); +		show_boot_progress (49); -	checksum = ntohl(hdr->ih_hcrc); -	hdr->ih_hcrc = 0; +		if (!image_check_hcrc (hdr)) { +			puts ("\n** Bad Header Checksum **\n"); +			show_boot_progress (-50); +			return 1; +		} +		show_boot_progress (50); + +		image_print_contents (hdr); -	if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { -		puts ("\n** Bad Header Checksum **\n"); -		show_boot_progress (-50); +		cnt = image_get_image_size (hdr); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			show_boot_progress (-140); +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		show_boot_progress (141); +		puts ("Fit image detected...\n"); + +		cnt = fit_get_size (fit_hdr); +		break; +#endif +	default: +		show_boot_progress (-49); +		puts ("** Unknown image type\n");  		return 1;  	} -	show_boot_progress (50); -	hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ -	print_image_hdr (hdr); - -	cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));  	cnt += info.blksz - 1;  	cnt /= info.blksz;  	cnt -= 1; @@ -481,6 +498,11 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	}  	show_boot_progress (51); +#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) +		fit_print_contents ((const void *)addr); +#endif  	/* Loading ok, update default load address */ diff --git a/common/cmd_load.c b/common/cmd_load.c index 204c3ebf1..1b75a7b5e 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -521,8 +521,15 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		char *s;  		if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { -			printf("Running autoscript at addr 0x%08lX ...\n", load_addr); -			rcode = autoscript (load_addr); +			printf ("Running autoscript at addr 0x%08lX", load_addr); + +			s = getenv ("autoscript_uname"); +			if (s) +				printf (":%s ...\n", s); +			else +				puts (" ...\n"); + +			rcode = autoscript (load_addr, s);  		}  	}  #endif diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 8d6c95958..7b1f83046 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -484,6 +484,9 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,  	ulong cnt;  	image_header_t *hdr;  	int jffs2 = 0; +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif  	s = strchr(cmd, '.');  	if (s != NULL && @@ -512,18 +515,35 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,  	}  	show_boot_progress (56); -	hdr = (image_header_t *) addr; +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; + +		show_boot_progress (57); +		image_print_contents (hdr); -	if (ntohl(hdr->ih_magic) != IH_MAGIC) { -		printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); +		cnt = image_get_image_size (hdr); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			show_boot_progress (-150); +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		show_boot_progress (151); +		puts ("Fit image detected...\n"); + +		cnt = fit_get_size (fit_hdr); +		break; +#endif +	default:  		show_boot_progress (-57); +		puts ("** Unknown image type\n");  		return 1;  	} -	show_boot_progress (57); - -	print_image_hdr(hdr); -	cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));  	if (jffs2) {  		nand_read_options_t opts;  		memset(&opts, 0, sizeof(opts)); @@ -543,6 +563,12 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,  	}  	show_boot_progress (58); +#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) +		fit_print_contents ((const void *)addr); +#endif +  	/* Loading ok, update default load address */  	load_addr = addr; @@ -925,6 +951,10 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	ulong offset = 0;  	image_header_t *hdr;  	int rcode = 0; +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif +  	show_boot_progress (52);  	switch (argc) {  	case 1: @@ -980,17 +1010,31 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	}  	show_boot_progress (56); -	hdr = (image_header_t *)addr; - -	if (ntohl(hdr->ih_magic) == IH_MAGIC) { +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; +		image_print_contents (hdr); -		print_image_hdr (hdr); - -		cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); +		cnt = image_get_image_size (hdr);  		cnt -= SECTORSIZE; -	} else { -		printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic)); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			show_boot_progress (-150); +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		show_boot_progress (151); +		puts ("Fit image detected...\n"); + +		cnt = fit_get_size (fit_hdr); +		break; +#endif +	default:  		show_boot_progress (-57); +		puts ("** Unknown image type\n");  		return 1;  	}  	show_boot_progress (57); @@ -1004,6 +1048,12 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	}  	show_boot_progress (58); +#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) +		fit_print_contents ((const void *)addr); +#endif +  	/* Loading ok, update default load address */  	load_addr = addr; diff --git a/common/cmd_net.c b/common/cmd_net.c index dbf6b861b..79e910c76 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -220,9 +220,16 @@ netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[])  #ifdef CONFIG_AUTOSCRIPT  	if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { -		printf("Running autoscript at addr 0x%08lX ...\n", load_addr); +		printf ("Running autoscript at addr 0x%08lX", load_addr); + +		s = getenv ("autoscript_uname"); +		if (s) +			printf (":%s ...\n", s); +		else +			puts (" ...\n"); +  		show_boot_progress (83); -		rcode = autoscript (load_addr); +		rcode = autoscript (load_addr, s);  	}  #endif  	if (rcode < 0) diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 1cdec159f..f49531e96 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -207,10 +207,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	char *boot_device = NULL;  	char *ep;  	int dev, part = 0; -	ulong addr, cnt, checksum; +	ulong addr, cnt;  	disk_partition_t info;  	image_header_t *hdr;  	int rcode = 0; +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif  	switch (argc) {  	case 1: @@ -273,24 +276,35 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		return 1;  	} -	hdr = (image_header_t *)addr; +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; -	if (ntohl(hdr->ih_magic) == IH_MAGIC) { -		printf("\n** Bad Magic Number **\n"); -		return 1; -	} +		if (!image_check_hcrc (hdr)) { +			puts ("\n** Bad Header Checksum **\n"); +			return 1; +		} -	checksum = ntohl(hdr->ih_hcrc); -	hdr->ih_hcrc = 0; +		image_print_contents (hdr); +		cnt = image_get_image_size (hdr); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		puts ("Fit image detected...\n"); -	if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { -		puts ("\n** Bad Header Checksum **\n"); +		cnt = fit_get_size (fit_hdr); +		break; +#endif +	default: +		puts ("** Unknown image type\n");  		return 1;  	} -	hdr->ih_hcrc = htonl(checksum);	/* restore checksum for later use */ -	print_image_hdr (hdr); -	cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));  	cnt += info.blksz - 1;  	cnt /= info.blksz;  	cnt -= 1; @@ -300,6 +314,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		printf ("** Read error on %d:%d\n", dev, part);  		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) +		fit_print_contents ((const void *)addr); +#endif +  	/* Loading ok, update default load address */  	load_addr = addr; diff --git a/common/cmd_usb.c b/common/cmd_usb.c index ad3240708..23413b510 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -311,11 +311,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	char *boot_device = NULL;  	char *ep;  	int dev, part=1, rcode; -	ulong addr, cnt, checksum; +	ulong addr, cnt;  	disk_partition_t info;  	image_header_t *hdr;  	block_dev_desc_t *stor_dev; - +#if defined(CONFIG_FIT) +	const void *fit_hdr; +#endif  	switch (argc) {  	case 1: @@ -386,25 +388,36 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		return 1;  	} -	hdr = (image_header_t *)addr; +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: +		hdr = (image_header_t *)addr; -	if (ntohl(hdr->ih_magic) != IH_MAGIC) { -		printf("\n** Bad Magic Number **\n"); -		return 1; -	} +		if (!image_check_hcrc (hdr)) { +			puts ("\n** Bad Header Checksum **\n"); +			return 1; +		} -	checksum = ntohl(hdr->ih_hcrc); -	hdr->ih_hcrc = 0; +		image_print_contents (hdr); -	if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { -		puts ("\n** Bad Header Checksum **\n"); +		cnt = image_get_image_size (hdr); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			puts ("** Bad FIT image format\n"); +			return 1; +		} +		puts ("Fit image detected...\n"); + +		cnt = fit_get_size (fit_hdr); +		break; +#endif +	default: +		puts ("** Unknown image type\n");  		return 1;  	} -	hdr->ih_hcrc = htonl(checksum);	/* restore checksum for later use */ -	print_image_hdr (hdr); - -	cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));  	cnt += info.blksz - 1;  	cnt /= info.blksz;  	cnt -= 1; @@ -414,6 +427,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		printf ("\n** Read error on %d:%d\n", dev, part);  		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) +		fit_print_contents ((const void *)addr); +#endif +  	/* Loading ok, update default load address */  	load_addr = addr; diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 52e061449..7916fc197 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -24,7 +24,6 @@   * MA 02111-1307 USA   */ -#if defined(CONFIG_CMD_XIMG)  /*   * Multi Image extract @@ -37,92 +36,136 @@  int  do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  { -	ulong addr = load_addr, dest = 0; -	ulong data, len, checksum; -	ulong *len_ptr; -	int i, verify, part = 0; -	char pbuf[10], *s; -	image_header_t header; +	ulong		addr = load_addr; +	ulong		dest = 0; +	ulong		data, len, count; +	int		verify; +	int		part = 0; +	char		pbuf[10]; +	image_header_t	*hdr; +#if defined(CONFIG_FIT) +	const char	*uname = NULL; +	const void*	fit_hdr; +	int		noffset; +	const void	*fit_data; +	size_t		fit_len; +#endif -	s = getenv("verify"); -	verify = (s && (*s == 'n')) ? 0 : 1; +	verify = getenv_verify ();  	if (argc > 1) {  		addr = simple_strtoul(argv[1], NULL, 16);  	}  	if (argc > 2) {  		part = simple_strtoul(argv[2], NULL, 16); +#if defined(CONFIG_FIT) +		uname = argv[2]; +#endif  	}  	if (argc > 3) {  		dest = simple_strtoul(argv[3], NULL, 16);  	} -	printf("## Copying from image at %08lx ...\n", addr); - -	/* Copy header so we can blank CRC field for re-calculation */ -	memmove(&header, (char *) addr, sizeof (image_header_t)); - -	if (ntohl(header.ih_magic) != IH_MAGIC) { -		printf("Bad Magic Number\n"); -		return 1; -	} +	switch (genimg_get_format ((void *)addr)) { +	case IMAGE_FORMAT_LEGACY: -	data = (ulong) & header; -	len = sizeof (image_header_t); +		printf("## Copying part %d from legacy image " +			"at %08lx ...\n", part, addr); -	checksum = ntohl(header.ih_hcrc); -	header.ih_hcrc = 0; +		hdr = (image_header_t *)addr; +		if (!image_check_magic (hdr)) { +			printf("Bad Magic Number\n"); +			return 1; +		} -	if (crc32(0, (char *) data, len) != checksum) { -		printf("Bad Header Checksum\n"); -		return 1; -	} +		if (!image_check_hcrc (hdr)) { +			printf("Bad Header Checksum\n"); +			return 1; +		}  #ifdef DEBUG -	print_image_hdr((image_header_t *) addr); +		image_print_contents (hdr);  #endif -	data = addr + sizeof (image_header_t); -	len = ntohl(header.ih_size); +		if (!image_check_type (hdr, IH_TYPE_MULTI)) { +			printf("Wrong Image Type for %s command\n", +					cmdtp->name); +			return 1; +		} -	if (header.ih_type != IH_TYPE_MULTI) { -		printf("Wrong Image Type for %s command\n", cmdtp->name); -		return 1; -	} +		if (image_get_comp (hdr) != IH_COMP_NONE) { +			printf("Wrong Compression Type for %s command\n", +					cmdtp->name); +			return 1; +		} -	if (header.ih_comp != IH_COMP_NONE) { -		printf("Wrong Compression Type for %s command\n", cmdtp->name); -		return 1; -	} +		if (verify) { +			printf("   Verifying Checksum ... "); +			if (!image_check_dcrc (hdr)) { +				printf("Bad Data CRC\n"); +				return 1; +			} +			printf("OK\n"); +		} -	if (verify) { -		printf("   Verifying Checksum ... "); -		if (crc32(0, (char *) data, len) != ntohl(header.ih_dcrc)) { -			printf("Bad Data CRC\n"); +		count = image_multi_count (hdr); +		if (part >= count) { +			printf("Bad Image Part\n");  			return 1;  		} -		printf("OK\n"); -	} -	len_ptr = (ulong *) data; +		image_multi_getimg (hdr, part, &data, &len); +		break; +#if defined(CONFIG_FIT) +	case IMAGE_FORMAT_FIT: +		if (uname == NULL) { +			puts ("No FIT subimage unit name\n"); +			return 1; +		} + +		printf("## Copying '%s' subimage from FIT image " +			"at %08lx ...\n", uname, addr); + +		fit_hdr = (const void *)addr; +		if (!fit_check_format (fit_hdr)) { +			puts ("Bad FIT image format\n"); +			return 1; +		} + +		/* get subimage node offset */ +		noffset = fit_image_get_node (fit_hdr, uname); +		if (noffset < 0) { +			printf ("Can't find '%s' FIT subimage\n", uname); +			return 1; +		} -	data += 4;		/* terminator */ -	for (i = 0; len_ptr[i]; ++i) { -		data += 4; -		if (argc > 2 && part > i) { -			u_long tail; -			len = ntohl(len_ptr[i]); -			tail = len % 4; -			data += len; -			if (tail) { -				data += 4 - tail; +		if (fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE)) { +			printf("Wrong Compression Type for %s command\n", +					cmdtp->name); +			return 1; +		} + +		/* verify integrity */ +		if (verify) { +			if (!fit_image_check_hashes (fit_hdr, noffset)) { +				puts ("Bad Data Hash\n"); +				return 1;  			}  		} -	} -	if (argc > 2 && part >= i) { -		printf("Bad Image Part\n"); + +		/* get subimage data address and length */ +		if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { +			puts ("Could not find script subimage data\n"); +			return 1; +		} + +		data = (ulong)fit_data; +		len = (ulong)fit_len; +		break; +#endif +	default: +		puts ("Invalid image type for imxtract\n");  		return 1;  	} -	len = ntohl(len_ptr[part]);  	if (argc > 3) {  		memcpy((char *) dest, (char *) data, len); @@ -139,6 +182,9 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  U_BOOT_CMD(imxtract, 4, 1, do_imgextract,  	   "imxtract- extract a part of a multi-image\n",  	   "addr part [dest]\n" -	   "    - extract <part> from image at <addr> and copy to <dest>\n"); - +	   "    - extract <part> from legacy image at <addr> and copy to <dest>\n" +#if defined(CONFIG_FIT) +	   "addr uname [dest]\n" +	   "    - extract <uname> subimage from FIT image at <addr> and copy to <dest>\n"  #endif +); diff --git a/common/gunzip.c b/common/gunzip.c new file mode 100644 index 000000000..74f0bf9f3 --- /dev/null +++ b/common/gunzip.c @@ -0,0 +1,113 @@ +/* + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <image.h> +#include <malloc.h> +#include <zlib.h> + +#define	ZALLOC_ALIGNMENT	16 +#define HEAD_CRC		2 +#define EXTRA_FIELD		4 +#define ORIG_NAME		8 +#define COMMENT			0x10 +#define RESERVED		0xe0 +#define DEFLATED		8 + +int gunzip(void *, int, unsigned char *, unsigned long *); +void *zalloc(void *, unsigned, unsigned); +void zfree(void *, void *, unsigned); + +void *zalloc(void *x, unsigned items, unsigned size) +{ +	void *p; + +	size *= items; +	size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); + +	p = malloc (size); + +	return (p); +} + +void zfree(void *x, void *addr, unsigned nb) +{ +	free (addr); +} + +int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +{ +	z_stream s; +	int r, i, flags; + +	/* skip header */ +	i = 10; +	flags = src[3]; +	if (src[2] != DEFLATED || (flags & RESERVED) != 0) { +		puts ("Error: Bad gzipped data\n"); +		return (-1); +	} +	if ((flags & EXTRA_FIELD) != 0) +		i = 12 + src[10] + (src[11] << 8); +	if ((flags & ORIG_NAME) != 0) +		while (src[i++] != 0) +			; +	if ((flags & COMMENT) != 0) +		while (src[i++] != 0) +			; +	if ((flags & HEAD_CRC) != 0) +		i += 2; +	if (i >= *lenp) { +		puts ("Error: gunzip out of data in header\n"); +		return (-1); +	} + +	s.zalloc = zalloc; +	s.zfree = zfree; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) +	s.outcb = (cb_func)WATCHDOG_RESET; +#else +	s.outcb = Z_NULL; +#endif	/* CONFIG_HW_WATCHDOG */ + +	r = inflateInit2(&s, -MAX_WBITS); +	if (r != Z_OK) { +		printf ("Error: inflateInit2() returned %d\n", r); +		return (-1); +	} +	s.next_in = src + i; +	s.avail_in = *lenp - i; +	s.next_out = dst; +	s.avail_out = dstlen; +	r = inflate(&s, Z_FINISH); +	if (r != Z_OK && r != Z_STREAM_END) { +		printf ("Error: inflate() returned %d\n", r); +		return (-1); +	} +	*lenp = s.next_out - (unsigned char *) dst; +	inflateEnd(&s); + +	return (0); +} diff --git a/common/image.c b/common/image.c new file mode 100644 index 000000000..f04826a5c --- /dev/null +++ b/common/image.c @@ -0,0 +1,2541 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#ifndef USE_HOSTCC +#include <common.h> +#include <watchdog.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +#include <status_led.h> +#endif + +#ifdef CONFIG_HAS_DATAFLASH +#include <dataflash.h> +#endif + +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) +#include <rtc.h> +#endif + +#include <image.h> + +#if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT) +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> +#endif + +#if defined(CONFIG_FIT) +#include <md5.h> +#include <sha1.h> + +static int fit_check_ramdisk (const void *fit, int os_noffset, +		uint8_t arch, int verify); +#endif + +#ifdef CONFIG_CMD_BDI +extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, +						int verify); +#else +#include "mkimage.h" +#include <md5.h> +#include <time.h> +#include <image.h> +#endif /* !USE_HOSTCC*/ + +typedef struct table_entry { +	int	id;		/* as defined in image.h	*/ +	char	*sname;		/* short (input) name		*/ +	char	*lname;		/* long (output) name		*/ +} table_entry_t; + +static table_entry_t uimage_arch[] = { +	{	IH_ARCH_INVALID,	NULL,		"Invalid ARCH",	}, +	{	IH_ARCH_ALPHA,		"alpha",	"Alpha",	}, +	{	IH_ARCH_ARM,		"arm",		"ARM",		}, +	{	IH_ARCH_I386,		"x86",		"Intel x86",	}, +	{	IH_ARCH_IA64,		"ia64",		"IA64",		}, +	{	IH_ARCH_M68K,		"m68k",		"M68K",		}, +	{	IH_ARCH_MICROBLAZE,	"microblaze",	"MicroBlaze",	}, +	{	IH_ARCH_MIPS,		"mips",		"MIPS",		}, +	{	IH_ARCH_MIPS64,		"mips64",	"MIPS 64 Bit",	}, +	{	IH_ARCH_NIOS,		"nios",		"NIOS",		}, +	{	IH_ARCH_NIOS2,		"nios2",	"NIOS II",	}, +	{	IH_ARCH_PPC,		"ppc",		"PowerPC",	}, +	{	IH_ARCH_S390,		"s390",		"IBM S390",	}, +	{	IH_ARCH_SH,		"sh",		"SuperH",	}, +	{	IH_ARCH_SPARC,		"sparc",	"SPARC",	}, +	{	IH_ARCH_SPARC64,	"sparc64",	"SPARC 64 Bit",	}, +	{	IH_ARCH_BLACKFIN,	"blackfin",	"Blackfin",	}, +	{	IH_ARCH_AVR32,		"avr32",	"AVR32",	}, +	{	-1,			"",		"",		}, +}; + +static table_entry_t uimage_os[] = { +	{	IH_OS_INVALID,	NULL,		"Invalid OS",		}, +#if defined(CONFIG_ARTOS) || defined(USE_HOSTCC) +	{	IH_OS_ARTOS,	"artos",	"ARTOS",		}, +#endif +	{	IH_OS_LINUX,	"linux",	"Linux",		}, +#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) +	{	IH_OS_LYNXOS,	"lynxos",	"LynxOS",		}, +#endif +	{	IH_OS_NETBSD,	"netbsd",	"NetBSD",		}, +	{	IH_OS_RTEMS,	"rtems",	"RTEMS",		}, +	{	IH_OS_U_BOOT,	"u-boot",	"U-Boot",		}, +#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) +	{	IH_OS_QNX,	"qnx",		"QNX",			}, +	{	IH_OS_VXWORKS,	"vxworks",	"VxWorks",		}, +#endif +#ifdef USE_HOSTCC +	{	IH_OS_4_4BSD,	"4_4bsd",	"4_4BSD",		}, +	{	IH_OS_DELL,	"dell",		"Dell",			}, +	{	IH_OS_ESIX,	"esix",		"Esix",			}, +	{	IH_OS_FREEBSD,	"freebsd",	"FreeBSD",		}, +	{	IH_OS_IRIX,	"irix",		"Irix",			}, +	{	IH_OS_NCR,	"ncr",		"NCR",			}, +	{	IH_OS_OPENBSD,	"openbsd",	"OpenBSD",		}, +	{	IH_OS_PSOS,	"psos",		"pSOS",			}, +	{	IH_OS_SCO,	"sco",		"SCO",			}, +	{	IH_OS_SOLARIS,	"solaris",	"Solaris",		}, +	{	IH_OS_SVR4,	"svr4",		"SVR4",			}, +#endif +	{	-1,		"",		"",			}, +}; + +static table_entry_t uimage_type[] = { +	{	IH_TYPE_INVALID,    NULL,	  "Invalid Image",	}, +	{	IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image",	}, +	{	IH_TYPE_FIRMWARE,   "firmware",	  "Firmware",		}, +	{	IH_TYPE_KERNEL,	    "kernel",	  "Kernel Image",	}, +	{	IH_TYPE_MULTI,	    "multi",	  "Multi-File Image",	}, +	{	IH_TYPE_RAMDISK,    "ramdisk",	  "RAMDisk Image",	}, +	{	IH_TYPE_SCRIPT,     "script",	  "Script",		}, +	{	IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, +	{	IH_TYPE_FLATDT,     "flat_dt",    "Flat Device Tree",	}, +	{	-1,		    "",		  "",			}, +}; + +static table_entry_t uimage_comp[] = { +	{	IH_COMP_NONE,	"none",		"uncompressed",		}, +	{	IH_COMP_BZIP2,	"bzip2",	"bzip2 compressed",	}, +	{	IH_COMP_GZIP,	"gzip",		"gzip compressed",	}, +	{	-1,		"",		"",			}, +}; + +unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); +static void genimg_print_size (uint32_t size); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +static void genimg_print_time (time_t timestamp); +#endif + +/*****************************************************************************/ +/* Legacy format routines */ +/*****************************************************************************/ +int image_check_hcrc (image_header_t *hdr) +{ +	ulong hcrc; +	ulong len = image_get_header_size (); +	image_header_t header; + +	/* Copy header so we can blank CRC field for re-calculation */ +	memmove (&header, (char *)hdr, image_get_header_size ()); +	image_set_hcrc (&header, 0); + +	hcrc = crc32 (0, (unsigned char *)&header, len); + +	return (hcrc == image_get_hcrc (hdr)); +} + +int image_check_dcrc (image_header_t *hdr) +{ +	ulong data = image_get_data (hdr); +	ulong len = image_get_data_size (hdr); +	ulong dcrc = crc32 (0, (unsigned char *)data, len); + +	return (dcrc == image_get_dcrc (hdr)); +} + +#ifndef USE_HOSTCC +int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) +{ +	ulong dcrc = 0; +	ulong len = image_get_data_size (hdr); +	ulong data = image_get_data (hdr); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) +	ulong cdata = data; +	ulong edata = cdata + len; + +	while (cdata < edata) { +		ulong chunk = edata - cdata; + +		if (chunk > chunksz) +			chunk = chunksz; +		dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk); +		cdata += chunk; + +		WATCHDOG_RESET (); +	} +#else +	dcrc = crc32 (0, (unsigned char *)data, len); +#endif + +	return (dcrc == image_get_dcrc (hdr)); +} +#endif /* !USE_HOSTCC */ + +/** + * image_multi_count - get component (sub-image) count + * @hdr: pointer to the header of the multi component image + * + * image_multi_count() returns number of components in a multi + * component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + *     number of components + */ +ulong image_multi_count (image_header_t *hdr) +{ +	ulong i, count = 0; +	uint32_t *size; + +	/* get start of the image payload, which in case of multi +	 * component images that points to a table of component sizes */ +	size = (uint32_t *)image_get_data (hdr); + +	/* count non empty slots */ +	for (i = 0; size[i]; ++i) +		count++; + +	return count; +} + +/** + * image_multi_getimg - get component data address and size + * @hdr: pointer to the header of the multi component image + * @idx: index of the requested component + * @data: pointer to a ulong variable, will hold component data address + * @len: pointer to a ulong variable, will hold component size + * + * image_multi_getimg() returns size and data address for the requested + * component in a multi component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + *     data address and size of the component, if idx is valid + *     0 in data and len, if idx is out of range + */ +void image_multi_getimg (image_header_t *hdr, ulong idx, +			ulong *data, ulong *len) +{ +	int i; +	uint32_t *size; +	ulong offset, tail, count, img_data; + +	/* get number of component */ +	count = image_multi_count (hdr); + +	/* get start of the image payload, which in case of multi +	 * component images that points to a table of component sizes */ +	size = (uint32_t *)image_get_data (hdr); + +	/* get address of the proper component data start, which means +	 * skipping sizes table (add 1 for last, null entry) */ +	img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t); + +	if (idx < count) { +		*len = uimage_to_cpu (size[idx]); +		offset = 0; +		tail = 0; + +		/* go over all indices preceding requested component idx */ +		for (i = 0; i < idx; i++) { +			/* add up i-th component size */ +			offset += uimage_to_cpu (size[i]); + +			/* add up alignment for i-th component */ +			tail += (4 - uimage_to_cpu (size[i]) % 4); +		} + +		/* calculate idx-th component data address */ +		*data = img_data + offset + tail; +	} else { +		*len = 0; +		*data = 0; +	} +} + +static void image_print_type (image_header_t *hdr) +{ +	const char *os, *arch, *type, *comp; + +	os = genimg_get_os_name (image_get_os (hdr)); +	arch = genimg_get_arch_name (image_get_arch (hdr)); +	type = genimg_get_type_name (image_get_type (hdr)); +	comp = genimg_get_comp_name (image_get_comp (hdr)); + +	printf ("%s %s %s (%s)\n", arch, os, type, comp); +} + +/** + * __image_print_contents - prints out the contents of the legacy format image + * @hdr: pointer to the legacy format image header + * @p: pointer to prefix string + * + * __image_print_contents() formats a multi line legacy image contents description. + * The routine prints out all header fields followed by the size/offset data + * for MULTI/SCRIPT images. + * + * returns: + *     no returned results + */ +static void __image_print_contents (image_header_t *hdr, const char *p) +{ +	printf ("%sImage Name:   %.*s\n", p, IH_NMLEN, image_get_name (hdr)); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +	printf ("%sCreated:      ", p); +	genimg_print_time ((time_t)image_get_time (hdr)); +#endif +	printf ("%sImage Type:   ", p); +	image_print_type (hdr); +	printf ("%sData Size:    ", p); +	genimg_print_size (image_get_data_size (hdr)); +	printf ("%sLoad Address: %08x\n", p, image_get_load (hdr)); +	printf ("%sEntry Point:  %08x\n", p, image_get_ep (hdr)); + +	if (image_check_type (hdr, IH_TYPE_MULTI) || +			image_check_type (hdr, IH_TYPE_SCRIPT)) { +		int i; +		ulong data, len; +		ulong count = image_multi_count (hdr); + +		printf ("%sContents:\n", p); +		for (i = 0; i < count; i++) { +			image_multi_getimg (hdr, i, &data, &len); + +			printf ("%s   Image %d: ", p, i); +			genimg_print_size (len); + +			if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) { +				/* +				 * the user may need to know offsets +				 * if planning to do something with +				 * multiple files +				 */ +				printf ("%s    Offset = 0x%08lx\n", p, data); +			} +		} +	} +} + +inline void image_print_contents (image_header_t *hdr) +{ +	__image_print_contents (hdr, "   "); +} + +inline void image_print_contents_noindent (image_header_t *hdr) +{ +	__image_print_contents (hdr, ""); +} + +#ifndef USE_HOSTCC +/** + * image_get_ramdisk - get and verify ramdisk image + * @rd_addr: ramdisk image start address + * @arch: expected ramdisk architecture + * @verify: checksum verification flag + * + * image_get_ramdisk() returns a pointer to the verified ramdisk image + * header. Routine receives image start address and expected architecture + * flag. Verification done covers data and header integrity and os/type/arch + * fields checking. + * + * If dataflash support is enabled routine checks for dataflash addresses + * and handles required dataflash reads. + * + * returns: + *     pointer to a ramdisk image header, if image was found and valid + *     otherwise, return NULL + */ +static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, +						int verify) +{ +	image_header_t *rd_hdr = (image_header_t *)rd_addr; + +	if (!image_check_magic (rd_hdr)) { +		puts ("Bad Magic Number\n"); +		show_boot_progress (-10); +		return NULL; +	} + +	if (!image_check_hcrc (rd_hdr)) { +		puts ("Bad Header Checksum\n"); +		show_boot_progress (-11); +		return NULL; +	} + +	show_boot_progress (10); +	image_print_contents (rd_hdr); + +	if (verify) { +		puts("   Verifying Checksum ... "); +		if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { +			puts ("Bad Data CRC\n"); +			show_boot_progress (-12); +			return NULL; +		} +		puts("OK\n"); +	} + +	show_boot_progress (11); + +	if (!image_check_os (rd_hdr, IH_OS_LINUX) || +	    !image_check_arch (rd_hdr, arch) || +	    !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { +		printf ("No Linux %s Ramdisk Image\n", +				genimg_get_arch_name(arch)); +		show_boot_progress (-13); +		return NULL; +	} + +	return rd_hdr; +} +#endif /* !USE_HOSTCC */ + +/*****************************************************************************/ +/* Shared dual-format routines */ +/*****************************************************************************/ +#ifndef USE_HOSTCC +int getenv_verify (void) +{ +	char *s = getenv ("verify"); +	return (s && (*s == 'n')) ? 0 : 1; +} + +int getenv_autostart (void) +{ +	char *s = getenv ("autostart"); +	return (s && (*s == 'n')) ? 0 : 1; +} + +ulong getenv_bootm_low(void) +{ +	char *s = getenv ("bootm_low"); +	if (s) { +		ulong tmp = simple_strtoul (s, NULL, 16); +		return tmp; +	} + +#if defined(CFG_SDRAM_BASE) +	return CFG_SDRAM_BASE; +#elif defined(CONFIG_ARM) +	return gd->bd->bi_dram[0].start; +#else +	return 0; +#endif +} + +ulong getenv_bootm_size(void) +{ +	char *s = getenv ("bootm_size"); +	if (s) { +		ulong tmp = simple_strtoul (s, NULL, 16); +		return tmp; +	} + +#if defined(CONFIG_ARM) +	return gd->bd->bi_dram[0].size; +#else +	return gd->bd->bi_memsize; +#endif +} + +void memmove_wd (void *to, void *from, size_t len, ulong chunksz) +{ +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) +	while (len > 0) { +		size_t tail = (len > chunksz) ? chunksz : len; +		WATCHDOG_RESET (); +		memmove (to, from, tail); +		to += tail; +		from += tail; +		len -= tail; +	} +#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ +	memmove (to, from, len); +#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +} +#endif /* !USE_HOSTCC */ + +static void genimg_print_size (uint32_t size) +{ +#ifndef USE_HOSTCC +	printf ("%d Bytes = ", size); +	print_size (size, "\n"); +#else +	printf ("%d Bytes = %.2f kB = %.2f MB\n", +			size, (double)size / 1.024e3, +			(double)size / 1.048576e6); +#endif +} + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +static void genimg_print_time (time_t timestamp) +{ +#ifndef USE_HOSTCC +	struct rtc_time tm; + +	to_tm (timestamp, &tm); +	printf ("%4d-%02d-%02d  %2d:%02d:%02d UTC\n", +			tm.tm_year, tm.tm_mon, tm.tm_mday, +			tm.tm_hour, tm.tm_min, tm.tm_sec); +#else +	printf ("%s", ctime(×tamp)); +#endif +} +#endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */ + +/** + * get_table_entry_name - translate entry id to long name + * @table: pointer to a translation table for entries of a specific type + * @msg: message to be returned when translation fails + * @id: entry id to be translated + * + * get_table_entry_name() will go over translation table trying to find + * entry that matches given id. If matching entry is found, its long + * name is returned to the caller. + * + * returns: + *     long entry name if translation succeeds + *     msg otherwise + */ +static char *get_table_entry_name (table_entry_t *table, char *msg, int id) +{ +	for (; table->id >= 0; ++table) { +		if (table->id == id) +			return (table->lname); +	} +	return (msg); +} + +const char *genimg_get_os_name (uint8_t os) +{ +	return (get_table_entry_name (uimage_os, "Unknown OS", os)); +} + +const char *genimg_get_arch_name (uint8_t arch) +{ +	return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch)); +} + +const char *genimg_get_type_name (uint8_t type) +{ +	return (get_table_entry_name (uimage_type, "Unknown Image", type)); +} + +const char *genimg_get_comp_name (uint8_t comp) +{ +	return (get_table_entry_name (uimage_comp, "Unknown Compression", comp)); +} + +/** + * get_table_entry_id - translate short entry name to id + * @table: pointer to a translation table for entries of a specific type + * @table_name: to be used in case of error + * @name: entry short name to be translated + * + * get_table_entry_id() will go over translation table trying to find + * entry that matches given short name. If matching entry is found, + * its id returned to the caller. + * + * returns: + *     entry id if translation succeeds + *     -1 otherwise + */ +static int get_table_entry_id (table_entry_t *table, +		const char *table_name, const char *name) +{ +	table_entry_t *t; +#ifdef USE_HOSTCC +	int first = 1; + +	for (t = table; t->id >= 0; ++t) { +		if (t->sname && strcasecmp(t->sname, name) == 0) +			return (t->id); +	} + +	fprintf (stderr, "\nInvalid %s Type - valid names are", table_name); +	for (t = table; t->id >= 0; ++t) { +		if (t->sname == NULL) +			continue; +		fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); +		first = 0; +	} +	fprintf (stderr, "\n"); +#else +	for (t = table; t->id >= 0; ++t) { +		if (t->sname && strcmp(t->sname, name) == 0) +			return (t->id); +	} +	debug ("Invalid %s Type: %s\n", table_name, name); +#endif /* USE_HOSTCC */ +	return (-1); +} + +int genimg_get_os_id (const char *name) +{ +	return (get_table_entry_id (uimage_os, "OS", name)); +} + +int genimg_get_arch_id (const char *name) +{ +	return (get_table_entry_id (uimage_arch, "CPU", name)); +} + +int genimg_get_type_id (const char *name) +{ +	return (get_table_entry_id (uimage_type, "Image", name)); +} + +int genimg_get_comp_id (const char *name) +{ +	return (get_table_entry_id (uimage_comp, "Compression", name)); +} + +#ifndef USE_HOSTCC +/** + * genimg_get_format - get image format type + * @img_addr: image start address + * + * genimg_get_format() checks whether provided address points to a valid + * legacy or FIT image. + * + * New uImage format and FDT blob are based on a libfdt. FDT blob + * may be passed directly or embedded in a FIT image. In both situations + * genimg_get_format() must be able to dectect libfdt header. + * + * returns: + *     image format type or IMAGE_FORMAT_INVALID if no image is present + */ +int genimg_get_format (void *img_addr) +{ +	ulong		format = IMAGE_FORMAT_INVALID; +	image_header_t	*hdr; +#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) +	char		*fit_hdr; +#endif + +	hdr = (image_header_t *)img_addr; +	if (image_check_magic(hdr)) +		format = IMAGE_FORMAT_LEGACY; +#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) +	else { +		fit_hdr = (char *)img_addr; +		if (fdt_check_header (fit_hdr) == 0) +			format = IMAGE_FORMAT_FIT; +	} +#endif + +	return format; +} + +/** + * genimg_get_image - get image from special storage (if necessary) + * @img_addr: image start address + * + * genimg_get_image() checks if provided image start adddress is located + * in a dataflash storage. If so, image is moved to a system RAM memory. + * + * returns: + *     image start address after possible relocation from special storage + */ +ulong genimg_get_image (ulong img_addr) +{ +	ulong ram_addr = img_addr; + +#ifdef CONFIG_HAS_DATAFLASH +	ulong h_size, d_size; + +	if (addr_dataflash (img_addr)){ +		/* ger RAM address */ +		ram_addr = CFG_LOAD_ADDR; + +		/* get header size */ +		h_size = image_get_header_size (); +#if defined(CONFIG_FIT) +		if (sizeof(struct fdt_header) > h_size) +			h_size = sizeof(struct fdt_header); +#endif + +		/* read in header */ +		debug ("   Reading image header from dataflash address " +			"%08lx to RAM address %08lx\n", img_addr, ram_addr); + +		read_dataflash (img_addr, h_size, (char *)ram_addr); + +		/* get data size */ +		switch (genimg_get_format ((void *)ram_addr)) { +		case IMAGE_FORMAT_LEGACY: +			d_size = image_get_data_size ((image_header_t *)ram_addr); +			debug ("   Legacy format image found at 0x%08lx, size 0x%08lx\n", +					ram_addr, d_size); +			break; +#if defined(CONFIG_FIT) +		case IMAGE_FORMAT_FIT: +			d_size = fit_get_size ((const void *)ram_addr) - h_size; +			debug ("   FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", +					ram_addr, d_size); +			break; +#endif +		default: +			printf ("   No valid image found at 0x%08lx\n", img_addr); +			return ram_addr; +		} + +		/* read in image data */ +		debug ("   Reading image remaining data from dataflash address " +			"%08lx to RAM address %08lx\n", img_addr + h_size, +			ram_addr + h_size); + +		read_dataflash (img_addr + h_size, d_size, +				(char *)(ram_addr + h_size)); + +	} +#endif /* CONFIG_HAS_DATAFLASH */ + +	return ram_addr; +} + +/** + * fit_has_config - check if there is a valid FIT configuration + * @images: pointer to the bootm command headers structure + * + * fit_has_config() checks if there is a FIT configuration in use + * (if FTI support is present). + * + * returns: + *     0, no FIT support or no configuration found + *     1, configuration found + */ +int genimg_has_config (bootm_headers_t *images) +{ +#if defined(CONFIG_FIT) +	if (images->fit_uname_cfg) +		return 1; +#endif +	return 0; +} + +/** + * boot_get_ramdisk - main ramdisk handling routine + * @argc: command argument count + * @argv: command argument list + * @images: pointer to the bootm images structure + * @arch: expected ramdisk architecture + * @rd_start: pointer to a ulong variable, will hold ramdisk start address + * @rd_end: pointer to a ulong variable, will hold ramdisk end + * + * boot_get_ramdisk() is responsible for finding a valid ramdisk image. + * Curently supported are the following ramdisk sources: + *      - multicomponent kernel/ramdisk image, + *      - commandline provided address of decicated ramdisk image. + * + * returns: + *     0, if ramdisk image was found and valid, or skiped + *     rd_start and rd_end are set to ramdisk start/end addresses if + *     ramdisk image is found and valid + * + *     1, if ramdisk image is found but corrupted + *     rd_start and rd_end are set to 0 if no ramdisk exists + */ +int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, +		uint8_t arch, ulong *rd_start, ulong *rd_end) +{ +	ulong rd_addr, rd_load; +	ulong rd_data, rd_len; +	image_header_t *rd_hdr; +#if defined(CONFIG_FIT) +	void		*fit_hdr; +	const char	*fit_uname_config = NULL; +	const char	*fit_uname_ramdisk = NULL; +	ulong		default_addr; +	int		rd_noffset; +	int		cfg_noffset; +	const void	*data; +	size_t		size; +#endif + +	*rd_start = 0; +	*rd_end = 0; + +	/* +	 * Look for a '-' which indicates to ignore the +	 * ramdisk argument +	 */ +	if ((argc >= 3) && (strcmp(argv[2], "-") ==  0)) { +		debug ("## Skipping init Ramdisk\n"); +		rd_len = rd_data = 0; +	} else if (argc >= 3 || genimg_has_config (images)) { +#if defined(CONFIG_FIT) +		if (argc >= 3) { +			/* +			 * If the init ramdisk comes from the FIT image and +			 * the FIT image address is omitted in the command +			 * line argument, try to use os FIT image address or +			 * default load address. +			 */ +			if (images->fit_uname_os) +				default_addr = (ulong)images->fit_hdr_os; +			else +				default_addr = load_addr; + +			if (fit_parse_conf (argv[2], default_addr, +						&rd_addr, &fit_uname_config)) { +				debug ("*  ramdisk: config '%s' from image at 0x%08lx\n", +						fit_uname_config, rd_addr); +			} else if (fit_parse_subimage (argv[2], default_addr, +						&rd_addr, &fit_uname_ramdisk)) { +				debug ("*  ramdisk: subimage '%s' from image at 0x%08lx\n", +						fit_uname_ramdisk, rd_addr); +			} else +#endif +			{ +				rd_addr = simple_strtoul(argv[2], NULL, 16); +				debug ("*  ramdisk: cmdline image address = 0x%08lx\n", +						rd_addr); +			} +#if defined(CONFIG_FIT) +		} else { +			/* use FIT configuration provided in first bootm +			 * command argument +			 */ +			rd_addr = (ulong)images->fit_hdr_os; +			fit_uname_config = images->fit_uname_cfg; +			debug ("*  ramdisk: using config '%s' from image at 0x%08lx\n", +					fit_uname_config, rd_addr); + +			/* +			 * Check whether configuration has ramdisk defined, +			 * if not, don't try to use it, quit silently. +			 */ +			fit_hdr = (void *)rd_addr; +			cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); +			if (cfg_noffset < 0) { +				debug ("*  ramdisk: no such config\n"); +				return 0; +			} + +			rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset); +			if (rd_noffset < 0) { +				debug ("*  ramdisk: no ramdisk in config\n"); +				return 0; +			} +		} +#endif + +		/* copy from dataflash if needed */ +		rd_addr = genimg_get_image (rd_addr); + +		/* +		 * Check if there is an initrd image at the +		 * address provided in the second bootm argument +		 * check image type, for FIT images get FIT node. +		 */ +		switch (genimg_get_format ((void *)rd_addr)) { +		case IMAGE_FORMAT_LEGACY: +			printf ("## Loading init Ramdisk from Legacy " +					"Image at %08lx ...\n", rd_addr); + +			show_boot_progress (9); +			rd_hdr = image_get_ramdisk (rd_addr, arch, +							images->verify); + +			if (rd_hdr == NULL) +				return 1; + +			rd_data = image_get_data (rd_hdr); +			rd_len = image_get_data_size (rd_hdr); +			rd_load = image_get_load (rd_hdr); +			break; +#if defined(CONFIG_FIT) +		case IMAGE_FORMAT_FIT: +			fit_hdr = (void *)rd_addr; +			printf ("## Loading init Ramdisk from FIT " +					"Image at %08lx ...\n", rd_addr); + +			show_boot_progress (120); +			if (!fit_check_format (fit_hdr)) { +				puts ("Bad FIT ramdisk image format!\n"); +				show_boot_progress (-120); +				return 0; +			} +			show_boot_progress (121); + +			if (!fit_uname_ramdisk) { +				/* +				 * no ramdisk image node unit name, try to get config +				 * node first. If config unit node name is NULL +				 * fit_conf_get_node() will try to find default config node +				 */ +				show_boot_progress (122); +				cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); +				if (cfg_noffset < 0) { +					puts ("Could not find configuration node\n"); +					show_boot_progress (-122); +					return 0; +				} +				fit_uname_config = fdt_get_name (fit_hdr, cfg_noffset, NULL); +				printf ("   Using '%s' configuration\n", fit_uname_config); + +				rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset); +				fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL); +			} else { +				/* get ramdisk component image node offset */ +				show_boot_progress (123); +				rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk); +			} +			if (rd_noffset < 0) { +				puts ("Could not find subimage node\n"); +				show_boot_progress (-124); +				return 0; +			} + +			printf ("   Trying '%s' ramdisk subimage\n", fit_uname_ramdisk); + +			show_boot_progress (125); +			if (!fit_check_ramdisk (fit_hdr, rd_noffset, arch, images->verify)) +				return 0; + +			/* get ramdisk image data address and length */ +			if (fit_image_get_data (fit_hdr, rd_noffset, &data, &size)) { +				puts ("Could not find ramdisk subimage data!\n"); +				show_boot_progress (-127); +				return 0; +			} +			show_boot_progress (128); + +			rd_data = (ulong)data; +			rd_len = size; + +			if (fit_image_get_load (fit_hdr, rd_noffset, &rd_load)) { +				puts ("Can't get ramdisk subimage load address!\n"); +				show_boot_progress (-129); +				return 0; +			} +			show_boot_progress (129); + +			images->fit_hdr_rd = fit_hdr; +			images->fit_uname_rd = fit_uname_ramdisk; +			images->fit_noffset_rd = rd_noffset; +			break; +#endif +		default: +			puts ("Wrong Ramdisk Image Format\n"); +			rd_data = rd_len = rd_load = 0; +		} + +#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) +		/* +		 * We need to copy the ramdisk to SRAM to let Linux boot +		 */ +		if (rd_data) { +			memmove ((void *)rd_load, (uchar *)rd_data, rd_len); +			rd_data = rd_load; +		} +#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ + +	} else if (images->legacy_hdr_valid && +			image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { +		/* +		 * Now check if we have a legacy mult-component image, +		 * get second entry data start address and len. +		 */ +		show_boot_progress (13); +		printf ("## Loading init Ramdisk from multi component " +				"Legacy Image at %08lx ...\n", +				(ulong)images->legacy_hdr_os); + +		image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len); +	} else { +		/* +		 * no initrd image +		 */ +		show_boot_progress (14); +		rd_len = rd_data = 0; +	} + +	if (!rd_data) { +		debug ("## No init Ramdisk\n"); +	} else { +		*rd_start = rd_data; +		*rd_end = rd_data + rd_len; +	} +	debug ("   ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", +			*rd_start, *rd_end); + +	return 0; +} + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +/** + * boot_ramdisk_high - relocate init ramdisk + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @rd_data: ramdisk data start address + * @rd_len: ramdisk data length + * @initrd_start: pointer to a ulong variable, will hold final init ramdisk + *      start address (after possible relocation) + * @initrd_end: pointer to a ulong variable, will hold final init ramdisk + *      end address (after possible relocation) + * + * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement + * variable and if requested ramdisk data is moved to a specified location. + * + * Initrd_start and initrd_end are set to final (after relocation) ramdisk + * start/end addresses if ramdisk image start and len were provided, + * otherwise set initrd_start and initrd_end set to zeros. + * + * returns: + *      0 - success + *     -1 - failure + */ +int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, +		  ulong *initrd_start, ulong *initrd_end) +{ +	char	*s; +	ulong	initrd_high; +	int	initrd_copy_to_ram = 1; + +	if ((s = getenv ("initrd_high")) != NULL) { +		/* a value of "no" or a similar string will act like 0, +		 * turning the "load high" feature off. This is intentional. +		 */ +		initrd_high = simple_strtoul (s, NULL, 16); +		if (initrd_high == ~0) +			initrd_copy_to_ram = 0; +	} else { +		/* not set, no restrictions to load high */ +		initrd_high = ~0; +	} + +	debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", +			initrd_high, initrd_copy_to_ram); + +	if (rd_data) { +		if (!initrd_copy_to_ram) {	/* zero-copy ramdisk support */ +			debug ("   in-place initrd\n"); +			*initrd_start = rd_data; +			*initrd_end = rd_data + rd_len; +			lmb_reserve(lmb, rd_data, rd_len); +		} else { +			if (initrd_high) +				*initrd_start = lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high); +			else +				*initrd_start = lmb_alloc (lmb, rd_len, 0x1000); + +			if (*initrd_start == 0) { +				puts ("ramdisk - allocation error\n"); +				goto error; +			} +			show_boot_progress (12); + +			*initrd_end = *initrd_start + rd_len; +			printf ("   Loading Ramdisk to %08lx, end %08lx ... ", +					*initrd_start, *initrd_end); + +			memmove_wd ((void *)*initrd_start, +					(void *)rd_data, rd_len, CHUNKSZ); + +			puts ("OK\n"); +		} +	} else { +		*initrd_start = 0; +		*initrd_end = 0; +	} +	debug ("   ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", +			*initrd_start, *initrd_end); + +	return 0; + +error: +	return -1; +} + +/** + * boot_get_cmdline - allocate and initialize kernel cmdline + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @cmd_start: pointer to a ulong variable, will hold cmdline start + * @cmd_end: pointer to a ulong variable, will hold cmdline end + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap + * + * boot_get_cmdline() allocates space for kernel command line below + * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt + * variable is present its contents is copied to allocated kernel + * command line. + * + * returns: + *      0 - success + *     -1 - failure + */ +int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, +			ulong bootmap_base) +{ +	char *cmdline; +	char *s; + +	cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, +					 CFG_BOOTMAPSZ + bootmap_base); + +	if (cmdline == NULL) +		return -1; + +	if ((s = getenv("bootargs")) == NULL) +		s = ""; + +	strcpy(cmdline, s); + +	*cmd_start = (ulong) & cmdline[0]; +	*cmd_end = *cmd_start + strlen(cmdline); + +	debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); + +	return 0; +} + +/** + * boot_get_kbd - allocate and initialize kernel copy of board info + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @kbd: double pointer to board info data + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap + * + * boot_get_kbd() allocates space for kernel copy of board info data below + * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with + * the current u-boot board info data. + * + * returns: + *      0 - success + *     -1 - failure + */ +int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) +{ +	*kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, +				      CFG_BOOTMAPSZ + bootmap_base); +	if (*kbd == NULL) +		return -1; + +	**kbd = *(gd->bd); + +	debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); + +#if defined(DEBUG) && defined(CONFIG_CMD_BDI) +	do_bdinfo(NULL, 0, 0, NULL); +#endif + +	return 0; +} +#endif /* CONFIG_PPC || CONFIG_M68K */ +#endif /* !USE_HOSTCC */ + +#if defined(CONFIG_FIT) +/*****************************************************************************/ +/* New uImage format routines */ +/*****************************************************************************/ +#ifndef USE_HOSTCC +static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, +		ulong *addr, const char **name) +{ +	const char *sep; + +	*addr = addr_curr; +	*name = NULL; + +	sep = strchr (spec, sepc); +	if (sep) { +		if (sep - spec > 0) +			*addr = simple_strtoul (spec, NULL, 16); + +		*name = sep + 1; +		return 1; +	} + +	return 0; +} + +/** + * fit_parse_conf - parse FIT configuration spec + * @spec: input string, containing configuration spec + * @add_curr: current image address (to be used as a possible default) + * @addr: pointer to a ulong variable, will hold FIT image address of a given + * configuration + * @conf_name double pointer to a char, will hold pointer to a configuration + * unit name + * + * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>, + * where <addr> is a FIT image address that contains configuration + * with a <conf> unit name. + * + * Address part is optional, and if omitted default add_curr will + * be used instead. + * + * returns: + *     1 if spec is a valid configuration string, + *     addr and conf_name are set accordingly + *     0 otherwise + */ +inline int fit_parse_conf (const char *spec, ulong addr_curr, +		ulong *addr, const char **conf_name) +{ +	return fit_parse_spec (spec, '#', addr_curr, addr, conf_name); +} + +/** + * fit_parse_subimage - parse FIT subimage spec + * @spec: input string, containing subimage spec + * @add_curr: current image address (to be used as a possible default) + * @addr: pointer to a ulong variable, will hold FIT image address of a given + * subimage + * @image_name: double pointer to a char, will hold pointer to a subimage name + * + * fit_parse_subimage() expects subimage spec in the for of + * [<addr>]:<subimage>, where <addr> is a FIT image address that contains + * subimage with a <subimg> unit name. + * + * Address part is optional, and if omitted default add_curr will + * be used instead. + * + * returns: + *     1 if spec is a valid subimage string, + *     addr and image_name are set accordingly + *     0 otherwise + */ +inline int fit_parse_subimage (const char *spec, ulong addr_curr, +		ulong *addr, const char **image_name) +{ +	return fit_parse_spec (spec, ':', addr_curr, addr, image_name); +} +#endif /* !USE_HOSTCC */ + +static void fit_get_debug (const void *fit, int noffset, +		char *prop_name, int err) +{ +	debug ("Can't get '%s' property from FIT 0x%08lx, " +		"node: offset %d, name %s (%s)\n", +		prop_name, (ulong)fit, noffset, +		fit_get_name (fit, noffset, NULL), +		fdt_strerror (err)); +} + +/** + * __fit_print_contents - prints out the contents of the FIT format image + * @fit: pointer to the FIT format image header + * @p: pointer to prefix string + * + * __fit_print_contents() formats a multi line FIT image contents description. + * The routine prints out FIT image properties (root node level) follwed by + * the details of each component image. + * + * returns: + *     no returned results + */ +static void __fit_print_contents (const void *fit, const char *p) +{ +	char *desc; +	char *uname; +	int images_noffset; +	int confs_noffset; +	int noffset; +	int ndepth; +	int count = 0; +	int ret; +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +	time_t timestamp; +#endif + +	/* Root node properties */ +	ret = fit_get_desc (fit, 0, &desc); +	printf ("%sFIT description: ", p); +	if (ret) +		printf ("unavailable\n"); +	else +		printf ("%s\n", desc); + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +	ret = fit_get_timestamp (fit, 0, ×tamp); +	printf ("%sCreated:         ", p); +	if (ret) +		printf ("unavailable\n"); +	else +		genimg_print_time (timestamp); +#endif + +	/* Find images parent node offset */ +	images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); +	if (images_noffset < 0) { +		printf ("Can't find images parent node '%s' (%s)\n", +			FIT_IMAGES_PATH, fdt_strerror (images_noffset)); +		return; +	} + +	/* Process its subnodes, print out component images details */ +	for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth); +	     (noffset >= 0) && (ndepth > 0); +	     noffset = fdt_next_node (fit, noffset, &ndepth)) { +		if (ndepth == 1) { +			/* +			 * Direct child node of the images parent node, +			 * i.e. component image node. +			 */ +			printf ("%s Image %u (%s)\n", p, count++, +					fit_get_name(fit, noffset, NULL)); + +			fit_image_print (fit, noffset, p); +		} +	} + +	/* Find configurations parent node offset */ +	confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH); +	if (confs_noffset < 0) { +		debug ("Can't get configurations parent node '%s' (%s)\n", +			FIT_CONFS_PATH, fdt_strerror (confs_noffset)); +		return; +	} + +	/* get default configuration unit name from default property */ +	uname = (char *)fdt_getprop (fit, noffset, FIT_DEFAULT_PROP, NULL); +	if (uname) +		printf ("%s Default Configuration: '%s'\n", p, uname); + +	/* Process its subnodes, print out configurations details */ +	for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, confs_noffset, &ndepth); +	     (noffset >= 0) && (ndepth > 0); +	     noffset = fdt_next_node (fit, noffset, &ndepth)) { +		if (ndepth == 1) { +			/* +			 * Direct child node of the configurations parent node, +			 * i.e. configuration node. +			 */ +			printf ("%s Configuration %u (%s)\n", p, count++, +					fit_get_name(fit, noffset, NULL)); + +			fit_conf_print (fit, noffset, p); +		} +	} +} + +inline void fit_print_contents (const void *fit) +{ +	__fit_print_contents (fit, "   "); +} + +inline void fit_print_contents_noindent (const void *fit) +{ +	__fit_print_contents (fit, ""); +} + +/** + * fit_image_print - prints out the FIT component image details + * @fit: pointer to the FIT format image header + * @image_noffset: offset of the component image node + * @p: pointer to prefix string + * + * fit_image_print() lists all mandatory properies for the processed component + * image. If present, hash nodes are printed out as well. + * + * returns: + *     no returned results + */ +void fit_image_print (const void *fit, int image_noffset, const char *p) +{ +	char *desc; +	uint8_t type, arch, os, comp; +	size_t size; +	ulong load, entry; +	const void *data; +	int noffset; +	int ndepth; +	int ret; + +	/* Mandatory properties */ +	ret = fit_get_desc (fit, image_noffset, &desc); +	printf ("%s  Description:  ", p); +	if (ret) +		printf ("unavailable\n"); +	else +		printf ("%s\n", desc); + +	fit_image_get_type (fit, image_noffset, &type); +	printf ("%s  Type:         %s\n", p, genimg_get_type_name (type)); + +	fit_image_get_comp (fit, image_noffset, &comp); +	printf ("%s  Compression:  %s\n", p, genimg_get_comp_name (comp)); + +	ret = fit_image_get_data (fit, image_noffset, &data, &size); + +#ifndef USE_HOSTCC +	printf ("%s  Data Start:   ", p); +	if (ret) +		printf ("unavailable\n"); +	else +		printf ("0x%08lx\n", (ulong)data); +#endif + +	printf ("%s  Data Size:    ", p); +	if (ret) +		printf ("unavailable\n"); +	else +		genimg_print_size (size); + +	/* Remaining, type dependent properties */ +	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || +	    (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || +	    (type == IH_TYPE_FLATDT)) { +		fit_image_get_arch (fit, image_noffset, &arch); +		printf ("%s  Architecture: %s\n", p, genimg_get_arch_name (arch)); +	} + +	if (type == IH_TYPE_KERNEL) { +		fit_image_get_os (fit, image_noffset, &os); +		printf ("%s  OS:           %s\n", p, genimg_get_os_name (os)); +	} + +	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { +		ret = fit_image_get_load (fit, image_noffset, &load); +		printf ("%s  Load Address: ", p); +		if (ret) +			printf ("unavailable\n"); +		else +			printf ("0x%08lx\n", load); + +		fit_image_get_entry (fit, image_noffset, &entry); +		printf ("%s  Entry Point:  ", p); +		if (ret) +			printf ("unavailable\n"); +		else +			printf ("0x%08lx\n", entry); +	} + +	/* Process all hash subnodes of the component image node */ +	for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); +	     (noffset >= 0) && (ndepth > 0); +	     noffset = fdt_next_node (fit, noffset, &ndepth)) { +		if (ndepth == 1) { +			/* Direct child node of the component image node */ +			fit_image_print_hash (fit, noffset, p); +		} +	} +} + +/** + * fit_image_print_hash - prints out the hash node details + * @fit: pointer to the FIT format image header + * @noffset: offset of the hash node + * @p: pointer to prefix string + * + * fit_image_print_hash() lists properies for the processed hash node + * + * returns: + *     no returned results + */ +void fit_image_print_hash (const void *fit, int noffset, const char *p) +{ +	char *algo; +	uint8_t *value; +	int value_len; +	int i, ret; + +	/* +	 * Check subnode name, must be equal to "hash". +	 * Multiple hash nodes require unique unit node +	 * names, e.g. hash@1, hash@2, etc. +	 */ +	if (strncmp (fit_get_name(fit, noffset, NULL), +			FIT_HASH_NODENAME, +			strlen(FIT_HASH_NODENAME)) != 0) +		return; + +	debug ("%s  Hash node:    '%s'\n", p, +			fit_get_name (fit, noffset, NULL)); + +	printf ("%s  Hash algo:    ", p); +	if (fit_image_hash_get_algo (fit, noffset, &algo)) { +		printf ("invalid/unsupported\n"); +		return; +	} +	printf ("%s\n", algo); + +	ret = fit_image_hash_get_value (fit, noffset, &value, +					&value_len); +	printf ("%s  Hash value:   ", p); +	if (ret) { +		printf ("unavailable\n"); +	} else { +		for (i = 0; i < value_len; i++) +			printf ("%02x", value[i]); +		printf ("\n"); +	} + +	debug  ("%s  Hash len:     %d\n", p, value_len); +} + +/** + * fit_get_desc - get node description property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @desc: double pointer to the char, will hold pointer to the descrption + * + * fit_get_desc() reads description property from a given node, if + * description is found pointer to it is returened in third call argument. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_get_desc (const void *fit, int noffset, char **desc) +{ +	int len; + +	*desc = (char *)fdt_getprop (fit, noffset, FIT_DESC_PROP, &len); +	if (*desc == NULL) { +		fit_get_debug (fit, noffset, FIT_DESC_PROP, len); +		return -1; +	} + +	return 0; +} + +/** + * fit_get_timestamp - get node timestamp property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @timestamp: pointer to the time_t, will hold read timestamp + * + * fit_get_timestamp() reads timestamp poperty from given node, if timestamp + * is found and has a correct size its value is retured in third call + * argument. + * + * returns: + *     0, on success + *     -1, on property read failure + *     -2, on wrong timestamp size + */ +int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp) +{ +	int len; +	const void *data; + +	data = fdt_getprop (fit, noffset, FIT_TIMESTAMP_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_TIMESTAMP_PROP, len); +		return -1; +	} +	if (len != sizeof (uint32_t)) { +		debug ("FIT timestamp with incorrect size of (%u)\n", len); +		return -2; +	} + +	*timestamp = uimage_to_cpu (*((uint32_t *)data)); +	return 0; +} + +/** + * fit_image_get_node - get node offset for component image of a given unit name + * @fit: pointer to the FIT format image header + * @image_uname: component image node unit name + * + * fit_image_get_node() finds a component image (withing the '/images' + * node) of a provided unit name. If image is found its node offset is + * returned to the caller. + * + * returns: + *     image node offset when found (>=0) + *     negative number on failure (FDT_ERR_* code) + */ +int fit_image_get_node (const void *fit, const char *image_uname) +{ +	int noffset, images_noffset; + +	images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); +	if (images_noffset < 0) { +		debug ("Can't find images parent node '%s' (%s)\n", +			FIT_IMAGES_PATH, fdt_strerror (images_noffset)); +		return images_noffset; +	} + +	noffset = fdt_subnode_offset (fit, images_noffset, image_uname); +	if (noffset < 0) { +		debug ("Can't get node offset for image unit name: '%s' (%s)\n", +			image_uname, fdt_strerror (noffset)); +	} + +	return noffset; +} + +/** + * fit_image_get_os - get os id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @os: pointer to the uint8_t, will hold os numeric id + * + * fit_image_get_os() finds os property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_os (const void *fit, int noffset, uint8_t *os) +{ +	int len; +	const void *data; + +	/* Get OS name from property data */ +	data = fdt_getprop (fit, noffset, FIT_OS_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_OS_PROP, len); +		*os = -1; +		return -1; +	} + +	/* Translate OS name to id */ +	*os = genimg_get_os_id (data); +	return 0; +} + +/** + * fit_image_get_arch - get arch id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @arch: pointer to the uint8_t, will hold arch numeric id + * + * fit_image_get_arch() finds arch property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch) +{ +	int len; +	const void *data; + +	/* Get architecture name from property data */ +	data = fdt_getprop (fit, noffset, FIT_ARCH_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_ARCH_PROP, len); +		*arch = -1; +		return -1; +	} + +	/* Translate architecture name to id */ +	*arch = genimg_get_arch_id (data); +	return 0; +} + +/** + * fit_image_get_type - get type id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @type: pointer to the uint8_t, will hold type numeric id + * + * fit_image_get_type() finds type property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_type (const void *fit, int noffset, uint8_t *type) +{ +	int len; +	const void *data; + +	/* Get image type name from property data */ +	data = fdt_getprop (fit, noffset, FIT_TYPE_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_TYPE_PROP, len); +		*type = -1; +		return -1; +	} + +	/* Translate image type name to id */ +	*type = genimg_get_type_id (data); +	return 0; +} + +/** + * fit_image_get_comp - get comp id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @comp: pointer to the uint8_t, will hold comp numeric id + * + * fit_image_get_comp() finds comp property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp) +{ +	int len; +	const void *data; + +	/* Get compression name from property data */ +	data = fdt_getprop (fit, noffset, FIT_COMP_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_COMP_PROP, len); +		*comp = -1; +		return -1; +	} + +	/* Translate compression name to id */ +	*comp = genimg_get_comp_id (data); +	return 0; +} + +/** + * fit_image_get_load - get load address property for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @load: pointer to the uint32_t, will hold load address + * + * fit_image_get_load() finds load address property in a given component image node. + * If the property is found, its value is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_load (const void *fit, int noffset, ulong *load) +{ +	int len; +	const uint32_t *data; + +	data = fdt_getprop (fit, noffset, FIT_LOAD_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_LOAD_PROP, len); +		return -1; +	} + +	*load = uimage_to_cpu (*data); +	return 0; +} + +/** + * fit_image_get_entry - get entry point address property for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @entry: pointer to the uint32_t, will hold entry point address + * + * fit_image_get_entry() finds entry point address property in a given component image node. + * If the property is found, its value is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_entry (const void *fit, int noffset, ulong *entry) +{ +	int len; +	const uint32_t *data; + +	data = fdt_getprop (fit, noffset, FIT_ENTRY_PROP, &len); +	if (data == NULL) { +		fit_get_debug (fit, noffset, FIT_ENTRY_PROP, len); +		return -1; +	} + +	*entry = uimage_to_cpu (*data); +	return 0; +} + +/** + * fit_image_get_data - get data property and its size for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @data: double pointer to void, will hold data property's data address + * @size: pointer to size_t, will hold data property's data size + * + * fit_image_get_data() finds data property in a given component image node. + * If the property is found its data start address and size are returned to + * the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_get_data (const void *fit, int noffset, +		const void **data, size_t *size) +{ +	int len; + +	*data = fdt_getprop (fit, noffset, FIT_DATA_PROP, &len); +	if (*data == NULL) { +		fit_get_debug (fit, noffset, FIT_DATA_PROP, len); +		*size = 0; +		return -1; +	} + +	*size = len; +	return 0; +} + +/** + * fit_image_hash_get_algo - get hash algorithm name + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @algo: double pointer to char, will hold pointer to the algorithm name + * + * fit_image_hash_get_algo() finds hash algorithm property in a given hash node. + * If the property is found its data start address is returned to the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_hash_get_algo (const void *fit, int noffset, char **algo) +{ +	int len; + +	*algo = (char *)fdt_getprop (fit, noffset, FIT_ALGO_PROP, &len); +	if (*algo == NULL) { +		fit_get_debug (fit, noffset, FIT_ALGO_PROP, len); +		return -1; +	} + +	return 0; +} + +/** + * fit_image_hash_get_value - get hash value and length + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: double pointer to uint8_t, will hold address of a hash value data + * @value_len: pointer to an int, will hold hash data length + * + * fit_image_hash_get_value() finds hash value property in a given hash node. + * If the property is found its data start address and size are returned to + * the caller. + * + * returns: + *     0, on success + *     -1, on failure + */ +int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value, +				int *value_len) +{ +	int len; + +	*value = (uint8_t *)fdt_getprop (fit, noffset, FIT_VALUE_PROP, &len); +	if (*value == NULL) { +		fit_get_debug (fit, noffset, FIT_VALUE_PROP, len); +		*value_len = 0; +		return -1; +	} + +	*value_len = len; +	return 0; +} + +/** + * fit_set_timestamp - set node timestamp property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @timestamp: timestamp value to be set + * + * fit_set_timestamp() attempts to set timestamp property in the requested + * node and returns operation status to the caller. + * + * returns: + *     0, on success + *     -1, on property read failure + */ +int fit_set_timestamp (void *fit, int noffset, time_t timestamp) +{ +	uint32_t t; +	int ret; + +	t = cpu_to_uimage (timestamp); +	ret = fdt_setprop (fit, noffset, FIT_TIMESTAMP_PROP, &t, +				sizeof (uint32_t)); +	if (ret) { +		printf ("Can't set '%s' property for '%s' node (%s)\n", +			FIT_TIMESTAMP_PROP, fit_get_name (fit, noffset, NULL), +			fdt_strerror (ret)); +		return -1; +	} + +	return 0; +} + +/** + * calculate_hash - calculate and return hash for provided input data + * @data: pointer to the input data + * @data_len: data length + * @algo: requested hash algorithm + * @value: pointer to the char, will hold hash value data (caller must + * allocate enough free space) + * value_len: length of the calculated hash + * + * calculate_hash() computes input data hash according to the requested algorithm. + * Resulting hash value is placed in caller provided 'value' buffer, length + * of the calculated hash is returned via value_len pointer argument. + * + * returns: + *     0, on success + *    -1, when algo is unsupported + */ +static int calculate_hash (const void *data, int data_len, const char *algo, +			uint8_t *value, int *value_len) +{ +	if (strcmp (algo, "crc32") == 0 ) { +		*((uint32_t *)value) = crc32 (0, data, data_len); +		*((uint32_t *)value) = cpu_to_uimage (*((uint32_t *)value)); +		*value_len = 4; +	} else if (strcmp (algo, "sha1") == 0 ) { +		sha1_csum ((unsigned char *) data, data_len, +				(unsigned char *) value); +		*value_len = 20; +	} else if (strcmp (algo, "md5") == 0 ) { +		md5 ((unsigned char *)data, data_len, value); +		*value_len = 16; +	} else { +		debug ("Unsupported hash alogrithm\n"); +		return -1; +	} +	return 0; +} + +#ifdef USE_HOSTCC +/** + * fit_set_hashes - process FIT component image nodes and calculate hashes + * @fit: pointer to the FIT format image header + * + * fit_set_hashes() adds hash values for all component images in the FIT blob. + * Hashes are calculated for all component images which have hash subnodes + * with algorithm property set to one of the supported hash algorithms. + * + * returns + *     0, on success + *     libfdt error code, on failure + */ +int fit_set_hashes (void *fit) +{ +	int images_noffset; +	int noffset; +	int ndepth; +	int ret; + +	/* Find images parent node offset */ +	images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); +	if (images_noffset < 0) { +		printf ("Can't find images parent node '%s' (%s)\n", +			FIT_IMAGES_PATH, fdt_strerror (images_noffset)); +		return images_noffset; +	} + +	/* Process its subnodes, print out component images details */ +	for (ndepth = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth); +	     (noffset >= 0) && (ndepth > 0); +	     noffset = fdt_next_node (fit, noffset, &ndepth)) { +		if (ndepth == 1) { +			/* +			 * Direct child node of the images parent node, +			 * i.e. component image node. +			 */ +			ret = fit_image_set_hashes (fit, noffset); +			if (ret) +				return ret; +		} +	} + +	return 0; +} + +/** + * fit_image_set_hashes - calculate/set hashes for given component image node + * @fit: pointer to the FIT format image header + * @image_noffset: requested component image node + * + * fit_image_set_hashes() adds hash values for an component image node. All + * existing hash subnodes are checked, if algorithm property is set to one of + * the supported hash algorithms, hash value is computed and corresponding + * hash node property is set, for example: + * + * Input component image node structure: + * + * o image@1 (at image_noffset) + *   | - data = [binary data] + *   o hash@1 + *     |- algo = "sha1" + * + * Output component image node structure: + * + * o image@1 (at image_noffset) + *   | - data = [binary data] + *   o hash@1 + *     |- algo = "sha1" + *     |- value = sha1(data) + * + * returns: + *     0 on sucess + *    <0 on failure + */ +int fit_image_set_hashes (void *fit, int image_noffset) +{ +	const void *data; +	size_t size; +	char *algo; +	uint8_t value[FIT_MAX_HASH_LEN]; +	int value_len; +	int noffset; +	int ndepth; + +	/* Get image data and data length */ +	if (fit_image_get_data (fit, image_noffset, &data, &size)) { +		printf ("Can't get image data/size\n"); +		return -1; +	} + +	/* Process all hash subnodes of the component image node */ +	for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); +	     (noffset >= 0) && (ndepth > 0); +	     noffset = fdt_next_node (fit, noffset, &ndepth)) { +		if (ndepth == 1) { +			/* Direct child node of the component image node */ + +			/* +			 * Check subnode name, must be equal to "hash". +			 * Multiple hash nodes require unique unit node +			 * names, e.g. hash@1, hash@2, etc. +			 */ +			if (strncmp (fit_get_name(fit, noffset, NULL), +						FIT_HASH_NODENAME, +						strlen(FIT_HASH_NODENAME)) != 0) { +				/* Not a hash subnode, skip it */ +				continue; +			} + +			if (fit_image_hash_get_algo (fit, noffset, &algo)) { +				printf ("Can't get hash algo property for " +					"'%s' hash node in '%s' image node\n", +					fit_get_name (fit, noffset, NULL), +					fit_get_name (fit, image_noffset, NULL)); +				return -1; +			} + +			if (calculate_hash (data, size, algo, value, &value_len)) { +				printf ("Unsupported hash algorithm (%s) for " +					"'%s' hash node in '%s' image node\n", +					algo, fit_get_name (fit, noffset, NULL), +					fit_get_name (fit, image_noffset, NULL)); +				return -1; +			} + +			if (fit_image_hash_set_value (fit, noffset, value, +							value_len)) { +				printf ("Can't set hash value for " +					"'%s' hash node in '%s' image node\n", +					fit_get_name (fit, noffset, NULL), +					fit_get_name (fit, image_noffset, NULL)); +				return -1; +			} +		} +	} + +	return 0; +} + +/** + * fit_image_hash_set_value - set hash value in requested has node + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: hash value to be set + * @value_len: hash value length + * + * fit_image_hash_set_value() attempts to set hash value in a node at offset + * given and returns operation status to the caller. + * + * returns + *     0, on success + *     -1, on failure + */ +int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value, +				int value_len) +{ +	int ret; + +	ret = fdt_setprop (fit, noffset, FIT_VALUE_PROP, value, value_len); +	if (ret) { +		printf ("Can't set hash '%s' property for '%s' node (%s)\n", +			FIT_VALUE_PROP, fit_get_name (fit, noffset, NULL), +			fdt_strerror (ret)); +		return -1; +	} + +	return 0; +} +#endif /* USE_HOSTCC */ + +/** + * fit_image_check_hashes - verify data intergity + * @fit: pointer to the FIT format image header + * @image_noffset: component image node offset + * + * fit_image_check_hashes() goes over component image hash nodes, + * re-calculates each data hash and compares with the value stored in hash + * node. + * + * returns: + *     1, if all hashes are valid + *     0, otherwise (or on error) + */ +int fit_image_check_hashes (const void *fit, int image_noffset) +{ +	const void	*data; +	size_t		size; +	char		*algo; +	uint8_t		*fit_value; +	int		fit_value_len; +	uint8_t		value[FIT_MAX_HASH_LEN]; +	int		value_len; +	int		noffset; +	int		ndepth; +	char		*err_msg = ""; + +	/* Get image data and data length */ +	if (fit_image_get_data (fit, image_noffset, &data, &size)) { +		printf ("Can't get image data/size\n"); +		return 0; +	} + +	/* Process all hash subnodes of the component image node */ +	for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); +	     (noffset >= 0) && (ndepth > 0); +	     noffset = fdt_next_node (fit, noffset, &ndepth)) { +		if (ndepth == 1) { +			/* Direct child node of the component image node */ + +			/* +			 * Check subnode name, must be equal to "hash". +			 * Multiple hash nodes require unique unit node +			 * names, e.g. hash@1, hash@2, etc. +			 */ +			if (strncmp (fit_get_name(fit, noffset, NULL), +					FIT_HASH_NODENAME, +					strlen(FIT_HASH_NODENAME)) != 0) +				continue; + +			if (fit_image_hash_get_algo (fit, noffset, &algo)) { +				err_msg = "Can't get hash algo property"; +				goto error; +			} +			printf ("%s", algo); + +			if (fit_image_hash_get_value (fit, noffset, &fit_value, +							&fit_value_len)) { +				err_msg = "Can't get hash value property"; +				goto error; +			} + +			if (calculate_hash (data, size, algo, value, &value_len)) { +				err_msg = "Unsupported hash algorithm"; +				goto error; +			} + +			if (value_len != fit_value_len) { +				err_msg = "Bad hash value len"; +				goto error; +			} else if (memcmp (value, fit_value, value_len) != 0) { +				err_msg = "Bad hash value"; +				goto error; +			} +			printf ("+ "); +		} +	} + +	return 1; + +error: +	printf ("%s for '%s' hash node in '%s' image node\n", +			err_msg, fit_get_name (fit, noffset, NULL), +			fit_get_name (fit, image_noffset, NULL)); +	return 0; +} + +/** + * fit_image_check_os - check whether image node is of a given os type + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @os: requested image os + * + * fit_image_check_os() reads image os property and compares its numeric + * id with the requested os. Comparison result is returned to the caller. + * + * returns: + *     1 if image is of given os type + *     0 otherwise (or on error) + */ +int fit_image_check_os (const void *fit, int noffset, uint8_t os) +{ +	uint8_t image_os; + +	if (fit_image_get_os (fit, noffset, &image_os)) +		return 0; +	return (os == image_os); +} + +/** + * fit_image_check_arch - check whether image node is of a given arch + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @arch: requested imagearch + * + * fit_image_check_arch() reads image arch property and compares its numeric + * id with the requested arch. Comparison result is returned to the caller. + * + * returns: + *     1 if image is of given arch + *     0 otherwise (or on error) + */ +int fit_image_check_arch (const void *fit, int noffset, uint8_t arch) +{ +	uint8_t image_arch; + +	if (fit_image_get_arch (fit, noffset, &image_arch)) +		return 0; +	return (arch == image_arch); +} + +/** + * fit_image_check_type - check whether image node is of a given type + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @type: requested image type + * + * fit_image_check_type() reads image type property and compares its numeric + * id with the requested type. Comparison result is returned to the caller. + * + * returns: + *     1 if image is of given type + *     0 otherwise (or on error) + */ +int fit_image_check_type (const void *fit, int noffset, uint8_t type) +{ +	uint8_t image_type; + +	if (fit_image_get_type (fit, noffset, &image_type)) +		return 0; +	return (type == image_type); +} + +/** + * fit_image_check_comp - check whether image node uses given compression + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @comp: requested image compression type + * + * fit_image_check_comp() reads image compression property and compares its + * numeric id with the requested compression type. Comparison result is + * returned to the caller. + * + * returns: + *     1 if image uses requested compression + *     0 otherwise (or on error) + */ +int fit_image_check_comp (const void *fit, int noffset, uint8_t comp) +{ +	uint8_t image_comp; + +	if (fit_image_get_comp (fit, noffset, &image_comp)) +		return 0; +	return (comp == image_comp); +} + +/** + * fit_check_format - sanity check FIT image format + * @fit: pointer to the FIT format image header + * + * fit_check_format() runs a basic sanity FIT image verification. + * Routine checks for mandatory properties, nodes, etc. + * + * returns: + *     1, on success + *     0, on failure + */ +int fit_check_format (const void *fit) +{ +	/* mandatory / node 'description' property */ +	if (fdt_getprop (fit, 0, FIT_DESC_PROP, NULL) == NULL) { +		debug ("Wrong FIT format: no description\n"); +		return 0; +	} + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +	/* mandatory / node 'timestamp' property */ +	if (fdt_getprop (fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) { +		debug ("Wrong FIT format: no description\n"); +		return 0; +	} +#endif + +	/* mandatory subimages parent '/images' node */ +	if (fdt_path_offset (fit, FIT_IMAGES_PATH) < 0) { +		debug ("Wrong FIT format: no images parent node\n"); +		return 0; +	} + +	return 1; +} + +/** + * fit_conf_get_node - get node offset for configuration of a given unit name + * @fit: pointer to the FIT format image header + * @conf_uname: configuration node unit name + * + * fit_conf_get_node() finds a configuration (withing the '/configurations' + * parant node) of a provided unit name. If configuration is found its node offset + * is returned to the caller. + * + * When NULL is provided in second argument fit_conf_get_node() will search + * for a default configuration node instead. Default configuration node unit name + * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node. + * + * returns: + *     configuration node offset when found (>=0) + *     negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_node (const void *fit, const char *conf_uname) +{ +	int noffset, confs_noffset; +	int len; + +	confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH); +	if (confs_noffset < 0) { +		debug ("Can't find configurations parent node '%s' (%s)\n", +			FIT_CONFS_PATH, fdt_strerror (confs_noffset)); +		return confs_noffset; +	} + +	if (conf_uname == NULL) { +		/* get configuration unit name from the default property */ +		debug ("No configuration specified, trying default...\n"); +		conf_uname = (char *)fdt_getprop (fit, confs_noffset, FIT_DEFAULT_PROP, &len); +		if (conf_uname == NULL) { +			fit_get_debug (fit, confs_noffset, FIT_DEFAULT_PROP, len); +			return len; +		} +		debug ("Found default configuration: '%s'\n", conf_uname); +	} + +	noffset = fdt_subnode_offset (fit, confs_noffset, conf_uname); +	if (noffset < 0) { +		debug ("Can't get node offset for configuration unit name: '%s' (%s)\n", +			conf_uname, fdt_strerror (noffset)); +	} + +	return noffset; +} + +static int __fit_conf_get_prop_node (const void *fit, int noffset, +		const char *prop_name) +{ +	char *uname; +	int len; + +	/* get kernel image unit name from configuration kernel property */ +	uname = (char *)fdt_getprop (fit, noffset, prop_name, &len); +	if (uname == NULL) +		return len; + +	return fit_image_get_node (fit, uname); +} + +/** + * fit_conf_get_kernel_node - get kernel image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_kernel_node() retrives kernel image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + *     image node offset when found (>=0) + *     negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_kernel_node (const void *fit, int noffset) +{ +	return __fit_conf_get_prop_node (fit, noffset, FIT_KERNEL_PROP); +} + +/** + * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + *     image node offset when found (>=0) + *     negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_ramdisk_node (const void *fit, int noffset) +{ +	return __fit_conf_get_prop_node (fit, noffset, FIT_RAMDISK_PROP); +} + +/** + * fit_conf_get_fdt_node - get fdt image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_fdt_node() retrives fdt image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + *     image node offset when found (>=0) + *     negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_fdt_node (const void *fit, int noffset) +{ +	return __fit_conf_get_prop_node (fit, noffset, FIT_FDT_PROP); +} + +/** + * fit_conf_print - prints out the FIT configuration details + * @fit: pointer to the FIT format image header + * @noffset: offset of the configuration node + * @p: pointer to prefix string + * + * fit_conf_print() lists all mandatory properies for the processed + * configuration node. + * + * returns: + *     no returned results + */ +void fit_conf_print (const void *fit, int noffset, const char *p) +{ +	char *desc; +	char *uname; +	int ret; + +	/* Mandatory properties */ +	ret = fit_get_desc (fit, noffset, &desc); +	printf ("%s  Description:  ", p); +	if (ret) +		printf ("unavailable\n"); +	else +		printf ("%s\n", desc); + +	uname = (char *)fdt_getprop (fit, noffset, FIT_KERNEL_PROP, NULL); +	printf ("%s  Kernel:       ", p); +	if (uname == NULL) +		printf ("unavailable\n"); +	else +		printf ("%s\n", uname); + +	/* Optional properties */ +	uname = (char *)fdt_getprop (fit, noffset, FIT_RAMDISK_PROP, NULL); +	if (uname) +		printf ("%s  Init Ramdisk: %s\n", p, uname); + +	uname = (char *)fdt_getprop (fit, noffset, FIT_FDT_PROP, NULL); +	if (uname) +		printf ("%s  FDT:          %s\n", p, uname); +} + +/** + * fit_check_ramdisk - verify FIT format ramdisk subimage + * @fit_hdr: pointer to the FIT ramdisk header + * @rd_noffset: ramdisk subimage node offset within FIT image + * @arch: requested ramdisk image architecture type + * @verify: data CRC verification flag + * + * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from + * specified FIT image. + * + * returns: + *     1, on success + *     0, on failure + */ +#ifndef USE_HOSTCC +static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int verify) +{ +	fit_image_print (fit, rd_noffset, "   "); + +	if (verify) { +		puts ("   Verifying Hash Integrity ... "); +		if (!fit_image_check_hashes (fit, rd_noffset)) { +			puts ("Bad Data Hash\n"); +			show_boot_progress (-125); +			return 0; +		} +		puts ("OK\n"); +	} + +	show_boot_progress (126); +	if (!fit_image_check_os (fit, rd_noffset, IH_OS_LINUX) || +	    !fit_image_check_arch (fit, rd_noffset, arch) || +	    !fit_image_check_type (fit, rd_noffset, IH_TYPE_RAMDISK)) { +		printf ("No Linux %s Ramdisk Image\n", +				genimg_get_arch_name(arch)); +		show_boot_progress (-126); +		return 0; +	} + +	show_boot_progress (127); +	return 1; +} +#endif /* USE_HOSTCC */ +#endif /* CONFIG_FIT */ diff --git a/common/lynxkdi.c b/common/lynxkdi.c index 76a271b96..a5dc88769 100644 --- a/common/lynxkdi.c +++ b/common/lynxkdi.c @@ -23,45 +23,45 @@  DECLARE_GLOBAL_DATA_PTR;  #if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR) -void lynxkdi_boot ( image_header_t *hdr ) +void lynxkdi_boot (image_header_t *hdr)  { -	void (*lynxkdi)(void) = (void(*)(void)) ntohl(hdr->ih_ep); +	void (*lynxkdi)(void) = (void(*)(void))image_get_ep (hdr);  	lynxos_bootparms_t *parms = (lynxos_bootparms_t *)0x0020;  	bd_t *kbd; -	u32 *psz = (u32 *)(ntohl(hdr->ih_load) + 0x0204); +	u32 *psz = (u32 *)(image_get_load (hdr) + 0x0204); -	memset( parms, 0, sizeof(*parms)); +	memset (parms, 0, sizeof(*parms));  	kbd = gd->bd;  	parms->clock_ref = kbd->bi_busfreq;  	parms->dramsz = kbd->bi_memsize; -	memcpy(parms->ethaddr, kbd->bi_enetaddr, 6); -	mtspr(SPRN_SPRG2, 0x0020); +	memcpy (parms->ethaddr, kbd->bi_enetaddr, 6); +	mtspr (SPRN_SPRG2, 0x0020);  	/* Do a simple check for Bluecat so we can pass the  	 * kernel command line parameters.  	 */ -	if( le32_to_cpu(*psz) == ntohl(hdr->ih_size) ){	/* FIXME: NOT SURE HERE ! */ -	    char *args; -	    char *cmdline = (char *)(ntohl(hdr->ih_load) + 0x020c); -	    int len; +	if (le32_to_cpu (*psz) == image_get_data_size (hdr)) {	/* FIXME: NOT SURE HERE ! */ +		char *args; +		char *cmdline = (char *)(image_get_load (hdr) + 0x020c); +		int len; -	    printf("Booting Bluecat KDI ...\n"); -	    udelay(200*1000); /* Allow serial port to flush */ -	    if ((args = getenv("bootargs")) == NULL) -		    args = ""; -	    /* Prepend the cmdline */ -	    len = strlen(args); -	    if( len && (len + strlen(cmdline) + 2 < (0x0400 - 0x020c))) { -		memmove( cmdline + strlen(args) + 1, cmdline, strlen(cmdline) ); -		strcpy( cmdline, args ); -		cmdline[len] = ' '; -	    } +		printf ("Booting Bluecat KDI ...\n"); +		udelay (200*1000); /* Allow serial port to flush */ +		if ((args = getenv ("bootargs")) == NULL) +			args = ""; +		/* Prepend the cmdline */ +		len = strlen (args); +		if (len && (len + strlen (cmdline) + 2 < (0x0400 - 0x020c))) { +			memmove (cmdline + strlen (args) + 1, cmdline, strlen (cmdline)); +			strcpy (cmdline, args); +			cmdline[len] = ' '; +		}  	}  	else { -	    printf("Booting LynxOS KDI ...\n"); +		printf ("Booting LynxOS KDI ...\n");  	} -	lynxkdi(); +	lynxkdi ();  }  #else  #error "Lynx KDI support not implemented for configured CPU" |