diff options
Diffstat (limited to 'common/cmd_bootm.c')
| -rw-r--r-- | common/cmd_bootm.c | 155 | 
1 files changed, 144 insertions, 11 deletions
| diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index daee7bf22..96d09e68d 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -66,6 +66,11 @@ static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);  static void fixup_silent_linux (void);  #endif +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[]); @@ -125,6 +130,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	ulong		image_start, image_end;  	ulong		load_start, load_end;  	ulong		mem_start, mem_size; +#if defined(CONFIG_FIT) +	int		os_noffset; +#endif  	struct lmb lmb; @@ -145,8 +153,10 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	/* get kernel image header, start address and length */  	os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,  			&images, &os_data, &os_len); -	if (os_len == 0) +	if (os_len == 0) { +		puts ("ERROR: can't get kernel image!\n");  		return 1; +	}  	show_boot_progress (6); @@ -162,8 +172,37 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		break;  #if defined(CONFIG_FIT)  	case IMAGE_FORMAT_FIT: -		fit_unsupported ("bootm"); -		return 1; +		os_noffset = fit_image_get_node (images.fit_hdr_os, +				images.fit_uname_os); +		if (os_noffset < 0) { +			printf ("Can't get image node for '%s'!\n", +					images.fit_uname_os); +			return 1; +		} + +		if (fit_image_get_type (images.fit_hdr_os, os_noffset, &type)) { +			puts ("Can't get image type!\n"); +			return 1; +		} + +		if (fit_image_get_comp (images.fit_hdr_os, os_noffset, &comp)) { +			puts ("Can't get image compression!\n"); +			return 1; +		} + +		if (fit_image_get_os (images.fit_hdr_os, os_noffset, &os)) { +			puts ("Can't get image OS!\n"); +			return 1; +		} + +		image_end = fit_get_end (images.fit_hdr_os); + +		if (fit_image_get_load (images.fit_hdr_os, os_noffset, +					&load_start)) { +			puts ("Can't get image load address!\n"); +			return 1; +		} +		break;  #endif  	default:  		puts ("ERROR: unknown image format type!\n"); @@ -360,6 +399,47 @@ static image_header_t *image_get_kernel (ulong img_addr, 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) +{ +	fit_image_print (fit, os_noffset, "   "); + +	if (verify) { +		puts ("   Verifying Hash Integrity ... "); +		if (!fit_image_check_hashes (fit, os_noffset)) { +			puts ("Bad Data Hash\n"); +			return 0; +		} +		puts ("OK\n"); +	} + +	if (!fit_image_check_target_arch (fit, os_noffset)) { +		puts ("Unsupported Architecture\n"); +		return 0; +	} + +	if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) { +		puts ("Not a kernel image\n"); +		return 0; +	} + +	return 1; +} +#endif /* CONFIG_FIT */ + +/**   * 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 @@ -380,6 +460,10 @@ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]  	void		*fit_hdr;  	const char	*fit_uname_config = NULL;  	const char	*fit_uname_kernel = NULL; +	const void	*data; +	size_t		len; +	int		conf_noffset; +	int		os_noffset;  #endif  	/* find out kernel image address */ @@ -403,21 +487,22 @@ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]  	}  	show_boot_progress (1); -	printf ("## Booting kernel image at %08lx ...\n", img_addr);  	/* copy from dataflash if needed */  	img_addr = genimg_get_image (img_addr);  	/* 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: - -		debug ("*  kernel: legacy format image\n"); +		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); +		/* get os_data and os_len */  		switch (image_get_type (hdr)) {  		case IH_TYPE_KERNEL:  			*os_data = image_get_data (hdr); @@ -438,17 +523,57 @@ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]  #if defined(CONFIG_FIT)  	case IMAGE_FORMAT_FIT:  		fit_hdr = (void *)img_addr; -		debug ("*  kernel: FIT format image\n"); -		fit_unsupported ("kernel"); -		return NULL; +		printf ("## Booting kernel from FIT Image at %08lx ...\n", +				img_addr); + +		if (!fit_check_format (fit_hdr)) { +			puts ("Bad FIT kernel image format!\n"); +			return NULL; +		} + +		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 +			 */ +			conf_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); +			if (conf_noffset < 0) +				return NULL; + +			os_noffset = fit_conf_get_kernel_node (fit_hdr, conf_noffset); +			fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); +		} else { +			/* get kernel component image node offset */ +			os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); +		} +		if (os_noffset < 0) +			return NULL; + +		printf ("   Trying '%s' kernel subimage\n", fit_uname_kernel); + +		if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) +			return NULL; + +		/* 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"); +			return NULL; +		} + +		*os_len = len; +		*os_data = (ulong)data; +		images->fit_hdr_os = fit_hdr; +		images->fit_uname_os = fit_uname_kernel; +		break;  #endif  	default:  		printf ("Wrong Image Format for %s command\n", cmdtp->name);  		return NULL;  	} -	debug ("   kernel data at 0x%08lx, end = 0x%08lx\n", -			*os_data, *os_data + *os_len); +	debug ("   kernel data at 0x%08lx, len = 0x%08lx (%d)\n", +			*os_data, *os_len, *os_len);  	return (void *)img_addr;  } @@ -466,6 +591,14 @@ U_BOOT_CMD(  	"\tuse a '-' for the second argument. If you do not pass a third\n"  	"\ta bd_info struct will be passed instead\n"  #endif +#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  );  /*******************************************************************/ |