diff options
Diffstat (limited to 'common')
35 files changed, 1004 insertions, 583 deletions
| diff --git a/common/Makefile b/common/Makefile index 54fcc8158..719fc231b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -152,6 +152,7 @@ COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o  COBJS-$(CONFIG_CMD_READ) += cmd_read.o  COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o  COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o +COBJS-$(CONFIG_SANDBOX) += cmd_sandbox.o  COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o  COBJS-$(CONFIG_CMD_SF) += cmd_sf.o  COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index f0338babe..2e9335207 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -79,9 +79,15 @@ static int image_info(unsigned long addr);  #include <flash.h>  #include <mtd/cfi_flash.h>  extern flash_info_t flash_info[]; /* info for FLASH chips */ +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)  static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);  #endif +#include <linux/err.h> +#include <nand.h> +  #ifdef CONFIG_SILENT_CONSOLE  static void fixup_silent_linux(void);  #endif @@ -446,9 +452,7 @@ static int bootm_start_standalone(ulong iflag, int argc, char * const argv[])  	/* Don't start if "autostart" is set to "no" */  	if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) { -		char buf[32]; -		sprintf(buf, "%lX", images.os.image_len); -		setenv("filesize", buf); +		setenv_hex("filesize", images.os.image_len);  		return 0;  	}  	appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep); @@ -523,17 +527,14 @@ static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,  		case BOOTM_STATE_RAMDISK:  		{  			ulong rd_len = images.rd_end - images.rd_start; -			char str[17];  			ret = boot_ramdisk_high(&images.lmb, images.rd_start,  				rd_len, &images.initrd_start, &images.initrd_end);  			if (ret)  				return ret; -			sprintf(str, "%lx", images.initrd_start); -			setenv("initrd_start", str); -			sprintf(str, "%lx", images.initrd_end); -			setenv("initrd_end", str); +			setenv_hex("initrd_start", images.initrd_start); +			setenv_hex("initrd_end", images.initrd_end);  		}  			break;  #endif @@ -1055,7 +1056,7 @@ static char bootm_help_text[] =  	"issued in the order below (it's ok to not issue all sub-commands):\n"  	"\tstart [addr [arg ...]]\n"  	"\tloados  - load OS image\n" -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)  	"\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"  #endif  #if defined(CONFIG_OF_LIBFDT) @@ -1192,7 +1193,7 @@ U_BOOT_CMD(  /* imls - list all images found in flash */  /*******************************************************************/  #if defined(CONFIG_CMD_IMLS) -static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_imls_nor(void)  {  	flash_info_t *info;  	int i, j; @@ -1241,6 +1242,161 @@ next_sector:		;  		}  next_bank:	;  	} +	return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS_NAND) +static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off, +		size_t len) +{ +	void *imgdata; +	int ret; + +	imgdata = malloc(len); +	if (!imgdata) { +		printf("May be a Legacy Image at NAND device %d offset %08llX:\n", +				nand_dev, off); +		printf("   Low memory(cannot allocate memory for image)\n"); +		return -ENOMEM; +	} + +	ret = nand_read_skip_bad(nand, off, &len, +			imgdata); +	if (ret < 0 && ret != -EUCLEAN) { +		free(imgdata); +		return ret; +	} + +	if (!image_check_hcrc(imgdata)) { +		free(imgdata); +		return 0; +	} + +	printf("Legacy Image at NAND device %d offset %08llX:\n", +			nand_dev, off); +	image_print_contents(imgdata); + +	puts("   Verifying Checksum ... "); +	if (!image_check_dcrc(imgdata)) +		puts("Bad Data CRC\n"); +	else +		puts("OK\n"); + +	free(imgdata); + +	return 0; +} + +static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off, +		size_t len) +{ +	void *imgdata; +	int ret; + +	imgdata = malloc(len); +	if (!imgdata) { +		printf("May be a FIT Image at NAND device %d offset %08llX:\n", +				nand_dev, off); +		printf("   Low memory(cannot allocate memory for image)\n"); +		return -ENOMEM; +	} + +	ret = nand_read_skip_bad(nand, off, &len, +			imgdata); +	if (ret < 0 && ret != -EUCLEAN) { +		free(imgdata); +		return ret; +	} + +	if (!fit_check_format(imgdata)) { +		free(imgdata); +		return 0; +	} + +	printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off); + +	fit_print_contents(imgdata); +	free(imgdata); + +	return 0; +} + +static int do_imls_nand(void) +{ +	nand_info_t *nand; +	int nand_dev = nand_curr_device; +	size_t len; +	loff_t off; +	u32 buffer[16]; + +	if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) { +		puts("\nNo NAND devices available\n"); +		return -ENODEV; +	} + +	printf("\n"); + +	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { +		nand = &nand_info[nand_dev]; +		if (!nand->name || !nand->size) +			continue; + +		for (off = 0; off < nand->size; off += nand->erasesize) { +			const image_header_t *header; +			int ret; + +			if (nand_block_isbad(nand, off)) +				continue; + +			len = sizeof(buffer); + +			ret = nand_read(nand, off, &len, (u8 *)buffer); +			if (ret < 0 && ret != -EUCLEAN) { +				printf("NAND read error %d at offset %08llX\n", +						ret, off); +				continue; +			} + +			switch (genimg_get_format(buffer)) { +			case IMAGE_FORMAT_LEGACY: +				header = (const image_header_t *)buffer; + +				len = image_get_image_size(header); +				nand_imls_legacyimage(nand, nand_dev, off, len); +				break; +#if defined(CONFIG_FIT) +			case IMAGE_FORMAT_FIT: +				len = fit_get_size(buffer); +				nand_imls_fitimage(nand, nand_dev, off, len); +				break; +#endif +			} +		} +	} + +	return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) +static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	int ret_nor = 0, ret_nand = 0; + +#if defined(CONFIG_CMD_IMLS) +	ret_nor = do_imls_nor(); +#endif + +#if defined(CONFIG_CMD_IMLS_NAND) +	ret_nand = do_imls_nand(); +#endif + +	if (ret_nor) +		return ret_nor; + +	if (ret_nand) +		return ret_nand;  	return (0);  } @@ -1249,8 +1405,8 @@ U_BOOT_CMD(  	imls,	1,		1,	do_imls,  	"list all images found in flash",  	"\n" -	"    - Prints information about all images found at sector\n" -	"      boundaries in flash." +	"    - Prints information about all images found at sector/block\n" +	"      boundaries in nor/nand flash."  );  #endif diff --git a/common/cmd_cbfs.c b/common/cmd_cbfs.c index 3b6cfd879..f51534b07 100644 --- a/common/cmd_cbfs.c +++ b/common/cmd_cbfs.c @@ -65,7 +65,6 @@ int do_cbfs_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])  	const struct cbfs_cachenode *file;  	unsigned long offset;  	unsigned long count; -	char buf[12];  	long size;  	if (argc < 3) { @@ -95,8 +94,7 @@ int do_cbfs_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])  	printf("\n%ld bytes read\n", size); -	sprintf(buf, "%lX", size); -	setenv("filesize", buf); +	setenv_hex("filesize", size);  	return 0;  } diff --git a/common/cmd_cramfs.c b/common/cmd_cramfs.c index e7f496e4e..0e43ab67c 100644 --- a/common/cmd_cramfs.c +++ b/common/cmd_cramfs.c @@ -146,11 +146,9 @@ int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		size = cramfs_load ((char *) offset, &part, filename);  	if (size > 0) { -		char buf[10];  		printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n",  			size, offset); -		sprintf(buf, "%x", size); -		setenv("filesize", buf); +		setenv_hex("filesize", size);  	} else {  		printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename);  	} diff --git a/common/cmd_elf.c b/common/cmd_elf.c index a667a469b..ab9c7e332 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -198,7 +198,7 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	 * defaults to 0x4200  	 */  	tmp = getenv("bootaddr"); -	if (tmp) +	if (!tmp)  		bootaddr = CONFIG_SYS_VXWORKS_BOOT_ADDR;  	else  		bootaddr = simple_strtoul(tmp, NULL, 16); diff --git a/common/cmd_fdos.c b/common/cmd_fdos.c index fbee8614c..8ea1140e7 100644 --- a/common/cmd_fdos.c +++ b/common/cmd_fdos.c @@ -40,7 +40,6 @@ int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])      char *name;      char *ep;      int size; -    char buf [12];      int drive = CONFIG_SYS_FDC_DRIVE_NUMBER;      /* pre-set load_addr */ @@ -91,8 +90,7 @@ int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])      }      flush_cache (load_addr, size); -    sprintf(buf, "%x", size); -    setenv("filesize", buf); +    setenv_hex("filesize", size);      printf("Floppy DOS load complete: %d bytes loaded to 0x%lx\n",  	   size, load_addr); diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 6eec947fc..ac77a08b7 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -55,12 +55,8 @@ struct fdt_header *working_fdt;  void set_working_fdt_addr(void *addr)  { -	char buf[17]; -  	working_fdt = addr; - -	sprintf(buf, "%lx", (unsigned long)addr); -	setenv("fdtaddr", buf); +	setenv_addr("fdtaddr", addr);  }  /* @@ -347,10 +343,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  			}  			if (subcmd[0] == 's') {  				/* get the num nodes at this level */ -				char buf[11]; - -				sprintf(buf, "%d", curIndex + 1); -				setenv(var, buf); +				setenv_ulong(var, curIndex + 1);  			} else {  				/* node index not found */  				printf("libfdt node not found\n"); diff --git a/common/cmd_gpt.c b/common/cmd_gpt.c index da7705da6..efd7934bd 100644 --- a/common/cmd_gpt.c +++ b/common/cmd_gpt.c @@ -27,6 +27,7 @@  #include <part_efi.h>  #include <exports.h>  #include <linux/ctype.h> +#include <div64.h>  #ifndef CONFIG_PARTITION_UUIDS  #error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled @@ -131,6 +132,7 @@ static int set_gpt_info(block_dev_desc_t *dev_desc,  	int p_count;  	disk_partition_t *parts;  	int errno = 0; +	uint64_t size_ll, start_ll;  	debug("%s: MMC lba num: 0x%x %d\n", __func__,  	      (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba); @@ -217,8 +219,8 @@ static int set_gpt_info(block_dev_desc_t *dev_desc,  		}  		if (extract_env(val, &p))  			p = val; -		parts[i].size = ustrtoul(p, &p, 0); -		parts[i].size /= dev_desc->blksz; +		size_ll = ustrtoull(p, &p, 0); +		parts[i].size = lldiv(size_ll, dev_desc->blksz);  		free(val);  		/* start address */ @@ -226,8 +228,8 @@ static int set_gpt_info(block_dev_desc_t *dev_desc,  		if (val) { /* start address is optional */  			if (extract_env(val, &p))  				p = val; -			parts[i].start = ustrtoul(p, &p, 0); -			parts[i].start /= dev_desc->blksz; +			start_ll = ustrtoull(p, &p, 0); +			parts[i].start = lldiv(start_ll, dev_desc->blksz);  			free(val);  		}  	} diff --git a/common/cmd_hash.c b/common/cmd_hash.c index 689c60857..4fe0e7861 100644 --- a/common/cmd_hash.c +++ b/common/cmd_hash.c @@ -26,22 +26,30 @@  #include <common.h>  #include <command.h>  #include <hash.h> +#include <linux/ctype.h>  static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  { +	char *s;  #ifdef CONFIG_HASH_VERIFY -	int verify = 0; +	int flags = HASH_FLAG_ENV; +	if (argc < 4) +		return CMD_RET_USAGE;  	if (!strcmp(argv[1], "-v")) { -		verify = 1; +		flags |= HASH_FLAG_VERIFY;  		argc--;  		argv++;  	} +#else +	const int flags = HASH_FLAG_ENV;  #endif  	/* Move forward to 'algorithm' parameter */  	argc--;  	argv++; -	return hash_command(*argv, verify, cmdtp, flag, argc - 1, argv + 1); +	for (s = *argv; *s; s++) +		*s = tolower(*s); +	return hash_command(*argv, flags, cmdtp, flag, argc - 1, argv + 1);  }  #ifdef CONFIG_HASH_VERIFY diff --git a/common/cmd_help.c b/common/cmd_help.c index f832a9697..d9bdc4d17 100644 --- a/common/cmd_help.c +++ b/common/cmd_help.c @@ -41,7 +41,7 @@ U_BOOT_CMD(  );  /* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */ -ll_entry_declare(cmd_tbl_t, question_mark, cmd, cmd) = { +ll_entry_declare(cmd_tbl_t, question_mark, cmd) = {  	"?",	CONFIG_SYS_MAXARGS,	1,	do_help,  	"alias for 'help'",  #ifdef  CONFIG_SYS_LONGHELP diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 27296ddd7..4a4a0000b 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -525,11 +525,9 @@ int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		}  		if (size > 0) { -			char buf[10];  			printf("### %s load complete: %d bytes loaded to 0x%lx\n",  				fsname, size, offset); -			sprintf(buf, "%x", size); -			setenv("filesize", buf); +			setenv_hex("filesize", size);  		} else {  			printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename);  		} diff --git a/common/cmd_load.c b/common/cmd_load.c index 2c8dab1a0..0832e92b1 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -149,7 +149,6 @@ static ulong load_serial(long offset)  	int	type;				/* return code for record type	*/  	ulong	addr;				/* load address from S-Record	*/  	ulong	size;				/* number of bytes transferred	*/ -	char	buf[32];  	ulong	store_addr;  	ulong	start_addr = ~0;  	ulong	end_addr   =  0; @@ -198,8 +197,7 @@ static ulong load_serial(long offset)  			    start_addr, end_addr, size, size  		    );  		    flush_cache(start_addr, size); -		    sprintf(buf, "%lX", size); -		    setenv("filesize", buf); +		    setenv_hex("filesize", size);  		    return (addr);  		case SREC_START:  		    break; @@ -519,7 +517,6 @@ static int do_load_serial_bin(cmd_tbl_t *cmdtp, int flag, int argc,  static ulong load_serial_bin(ulong offset)  {  	int size, i; -	char buf[32];  	set_kerm_bin_mode((ulong *) offset);  	size = k_recv(); @@ -539,8 +536,7 @@ static ulong load_serial_bin(ulong offset)  	flush_cache(offset, size);  	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size); -	sprintf(buf, "%X", size); -	setenv("filesize", buf); +	setenv_hex("filesize", size);  	return offset;  } @@ -965,7 +961,6 @@ static int getcxmodem(void) {  static ulong load_serial_ymodem(ulong offset)  {  	int size; -	char buf[32];  	int err;  	int res;  	connection_info_t info; @@ -1012,8 +1007,7 @@ static ulong load_serial_ymodem(ulong offset)  	flush_cache(offset, size);  	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size); -	sprintf(buf, "%X", size); -	setenv("filesize", buf); +	setenv_hex("filesize", size);  	return offset;  } @@ -1064,8 +1058,8 @@ U_BOOT_CMD(  	"    - save S-Record file over serial line with offset 'off' and size 'size'"  );  #endif	/* CONFIG_SYS_LOADS_BAUD_CHANGE */ -#endif -#endif +#endif	/* CONFIG_CMD_SAVES */ +#endif	/* CONFIG_CMD_LOADS */  #if defined(CONFIG_CMD_LOADB) @@ -1085,7 +1079,7 @@ U_BOOT_CMD(  	" with offset 'off' and baudrate 'baud'"  ); -#endif +#endif	/* CONFIG_CMD_LOADB */  /* -------------------------------------------------------------------- */ @@ -1115,4 +1109,4 @@ U_BOOT_CMD(  	"[on|off]"  ); -#endif +#endif	/* CONFIG_CMD_HWFLOW */ diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 0f3ffc84f..042c994a1 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -32,11 +32,17 @@  #ifdef CONFIG_HAS_DATAFLASH  #include <dataflash.h>  #endif +#include <hash.h>  #include <watchdog.h> +#include <asm/io.h>  #include <linux/compiler.h>  DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_SYS_MEMTEST_SCRATCH +#define CONFIG_SYS_MEMTEST_SCRATCH 0 +#endif +  static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);  /* Display values from last command. @@ -138,9 +144,13 @@ static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  # endif  	{ +		ulong bytes = size * length; +		const void *buf = map_sysmem(addr, bytes); +  		/* Print the lines. */ -		print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size); -		addr += size*length; +		print_buffer(addr, buf, size, length, DISP_LINE_LEN / size); +		addr += bytes; +		unmap_sysmem(buf);  	}  #endif @@ -163,6 +173,8 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	ulong	addr, writeval, count;  	int	size; +	void *buf; +	ulong bytes;  	if ((argc < 3) || (argc > 4))  		return CMD_RET_USAGE; @@ -188,15 +200,18 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		count = 1;  	} +	bytes = size * count; +	buf = map_sysmem(addr, bytes);  	while (count-- > 0) {  		if (size == 4) -			*((ulong  *)addr) = (ulong )writeval; +			*((ulong *)buf) = (ulong)writeval;  		else if (size == 2) -			*((ushort *)addr) = (ushort)writeval; +			*((ushort *)buf) = (ushort)writeval;  		else -			*((u_char *)addr) = (u_char)writeval; -		addr += size; +			*((u_char *)buf) = (u_char)writeval; +		buf += size;  	} +	unmap_sysmem(buf);  	return 0;  } @@ -258,10 +273,11 @@ int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  { -	ulong	addr1, addr2, count, ngood; +	ulong	addr1, addr2, count, ngood, bytes;  	int	size;  	int     rcode = 0;  	const char *type; +	const void *buf1, *buf2, *base;  	if (argc != 4)  		return CMD_RET_USAGE; @@ -294,33 +310,40 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	}  #endif +	bytes = size * count; +	base = buf1 = map_sysmem(addr1, bytes); +	buf2 = map_sysmem(addr2, bytes);  	for (ngood = 0; ngood < count; ++ngood) {  		ulong word1, word2;  		if (size == 4) { -			word1 = *(ulong *)addr1; -			word2 = *(ulong *)addr2; +			word1 = *(ulong *)buf1; +			word2 = *(ulong *)buf2;  		} else if (size == 2) { -			word1 = *(ushort *)addr1; -			word2 = *(ushort *)addr2; +			word1 = *(ushort *)buf1; +			word2 = *(ushort *)buf2;  		} else { -			word1 = *(u_char *)addr1; -			word2 = *(u_char *)addr2; +			word1 = *(u_char *)buf1; +			word2 = *(u_char *)buf2;  		}  		if (word1 != word2) { +			ulong offset = buf1 - base; +  			printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n", -				type, addr1, size, word1, -				type, addr2, size, word2); +				type, (ulong)(addr1 + offset), size, word1, +				type, (ulong)(addr2 + offset), size, word2);  			rcode = 1;  			break;  		} -		addr1 += size; -		addr2 += size; +		buf1 += size; +		buf2 += size;  		/* reset watchdog from time to time */  		if ((ngood % (64 << 10)) == 0)  			WATCHDOG_RESET();  	} +	unmap_sysmem(buf1); +	unmap_sysmem(buf2);  	printf("Total of %ld %s(s) were the same\n", ngood, type);  	return rcode; @@ -328,8 +351,10 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  { -	ulong	addr, dest, count; +	ulong	addr, dest, count, bytes;  	int	size; +	const void *src; +	void *buf;  	if (argc != 4)  		return CMD_RET_USAGE; @@ -419,15 +444,18 @@ static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	}  #endif +	bytes = size * count; +	buf = map_sysmem(addr, bytes); +	src = map_sysmem(addr, bytes);  	while (count-- > 0) {  		if (size == 4) -			*((ulong  *)dest) = *((ulong  *)addr); +			*((ulong *)buf) = *((ulong  *)src);  		else if (size == 2) -			*((ushort *)dest) = *((ushort *)addr); +			*((ushort *)buf) = *((ushort *)src);  		else -			*((u_char *)dest) = *((u_char *)addr); -		addr += size; -		dest += size; +			*((u_char *)buf) = *((u_char *)src); +		src += size; +		buf += size;  		/* reset watchdog from time to time */  		if ((count % (64 << 10)) == 0) @@ -453,16 +481,18 @@ static int do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,  static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,  		       char * const argv[])  { -	ulong	addr, length, i; +	ulong	addr, length, i, bytes;  	int	size;  	volatile uint	*longp;  	volatile ushort *shortp;  	volatile u_char	*cp; +	const void *buf;  	if (argc < 3)  		return CMD_RET_USAGE; -	/* Check for a size spefication. +	/* +	 * Check for a size specification.  	 * Defaults to long if no or incorrect specification.  	 */  	if ((size = cmd_get_data_size(argv[0], 4)) < 0) @@ -476,28 +506,31 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,  	*/  	length = simple_strtoul(argv[2], NULL, 16); +	bytes = size * length; +	buf = map_sysmem(addr, bytes); +  	/* We want to optimize the loops to run as fast as possible.  	 * If we have only one object, just run infinite loops.  	 */  	if (length == 1) {  		if (size == 4) { -			longp = (uint *)addr; +			longp = (uint *)buf;  			for (;;)  				i = *longp;  		}  		if (size == 2) { -			shortp = (ushort *)addr; +			shortp = (ushort *)buf;  			for (;;)  				i = *shortp;  		} -		cp = (u_char *)addr; +		cp = (u_char *)buf;  		for (;;)  			i = *cp;  	}  	if (size == 4) {  		for (;;) { -			longp = (uint *)addr; +			longp = (uint *)buf;  			i = length;  			while (i-- > 0)  				*longp++; @@ -505,33 +538,36 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,  	}  	if (size == 2) {  		for (;;) { -			shortp = (ushort *)addr; +			shortp = (ushort *)buf;  			i = length;  			while (i-- > 0)  				*shortp++;  		}  	}  	for (;;) { -		cp = (u_char *)addr; +		cp = (u_char *)buf;  		i = length;  		while (i-- > 0)  			*cp++;  	} +	unmap_sysmem(buf);  }  #ifdef CONFIG_LOOPW  int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  { -	ulong	addr, length, i, data; +	ulong	addr, length, i, data, bytes;  	int	size;  	volatile uint	*longp;  	volatile ushort *shortp;  	volatile u_char	*cp; +	void *buf;  	if (argc < 4)  		return CMD_RET_USAGE; -	/* Check for a size spefication. +	/* +	 * Check for a size specification.  	 * Defaults to long if no or incorrect specification.  	 */  	if ((size = cmd_get_data_size(argv[0], 4)) < 0) @@ -548,28 +584,31 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	/* data to write */  	data = simple_strtoul(argv[3], NULL, 16); +	bytes = size * length; +	buf = map_sysmem(addr, bytes); +  	/* We want to optimize the loops to run as fast as possible.  	 * If we have only one object, just run infinite loops.  	 */  	if (length == 1) {  		if (size == 4) { -			longp = (uint *)addr; +			longp = (uint *)buf;  			for (;;)  				*longp = data;  					}  		if (size == 2) { -			shortp = (ushort *)addr; +			shortp = (ushort *)buf;  			for (;;)  				*shortp = data;  		} -		cp = (u_char *)addr; +		cp = (u_char *)buf;  		for (;;)  			*cp = data;  	}  	if (size == 4) {  		for (;;) { -			longp = (uint *)addr; +			longp = (uint *)buf;  			i = length;  			while (i-- > 0)  				*longp++ = data; @@ -577,14 +616,14 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	}  	if (size == 2) {  		for (;;) { -			shortp = (ushort *)addr; +			shortp = (ushort *)buf;  			i = length;  			while (i-- > 0)  				*shortp++ = data;  		}  	}  	for (;;) { -		cp = (u_char *)addr; +		cp = (u_char *)buf;  		i = length;  		while (i-- > 0)  			*cp++ = data; @@ -592,36 +631,19 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  }  #endif /* CONFIG_LOOPW */ -/* - * Perform a memory test. A more complete alternative test can be - * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until - * interrupted by ctrl-c or by a failure of one of the sub-tests. - */ -static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, -			char * const argv[]) +static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr, +			  vu_long *dummy)  { -	vu_long	*addr, *start, *end; -	ulong	val; -	ulong	readback; -	ulong	errs = 0; -	int iterations = 1; -	int iteration_limit; - -#if defined(CONFIG_SYS_ALT_MEMTEST) -	vu_long	len; -	vu_long	offset; -	vu_long	test_offset; -	vu_long	pattern; -	vu_long	temp; -	vu_long	anti_pattern; -	vu_long	num_words; -#if defined(CONFIG_SYS_MEMTEST_SCRATCH) -	vu_long *dummy = (vu_long*)CONFIG_SYS_MEMTEST_SCRATCH; -#else -	vu_long *dummy = NULL;	/* yes, this is address 0x0, not NULL */ -#endif -	int	j; - +	vu_long *addr; +	ulong errs = 0; +	ulong val, readback; +	int j; +	vu_long offset; +	vu_long test_offset; +	vu_long pattern; +	vu_long temp; +	vu_long anti_pattern; +	vu_long num_words;  	static const ulong bitpattern[] = {  		0x00000001,	/* single bit */  		0x00000003,	/* two adjacent bits */ @@ -632,320 +654,353 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,  		0x00000055,	/* four non-adjacent bits */  		0xaaaaaaaa,	/* alternating 1/0 */  	}; -#else -	ulong	incr; -	ulong	pattern; -#endif - -	if (argc > 1) -		start = (ulong *)simple_strtoul(argv[1], NULL, 16); -	else -		start = (ulong *)CONFIG_SYS_MEMTEST_START; - -	if (argc > 2) -		end = (ulong *)simple_strtoul(argv[2], NULL, 16); -	else -		end = (ulong *)(CONFIG_SYS_MEMTEST_END); - -	if (argc > 3) -		pattern = (ulong)simple_strtoul(argv[3], NULL, 16); -	else -		pattern = 0; - -	if (argc > 4) -		iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16); -	else -		iteration_limit = 0; - -#if defined(CONFIG_SYS_ALT_MEMTEST) -	printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end); -	debug("%s:%d: start 0x%p end 0x%p\n", -		__FUNCTION__, __LINE__, start, end); - -	for (;;) { -		if (ctrlc()) { -			putc ('\n'); -			return 1; -		} +	num_words = (end_addr - start_addr) / sizeof(vu_long); -		if (iteration_limit && iterations > iteration_limit) { -			printf("Tested %d iteration(s) with %lu errors.\n", -				iterations-1, errs); -			return errs != 0; -		} - -		printf("Iteration: %6d\r", iterations); -		debug("\n"); -		iterations++; - -		/* -		 * Data line test: write a pattern to the first -		 * location, write the 1's complement to a 'parking' -		 * address (changes the state of the data bus so a -		 * floating bus doen't give a false OK), and then -		 * read the value back. Note that we read it back -		 * into a variable because the next time we read it, -		 * it might be right (been there, tough to explain to -		 * the quality guys why it prints a failure when the -		 * "is" and "should be" are obviously the same in the -		 * error message). -		 * -		 * Rather than exhaustively testing, we test some -		 * patterns by shifting '1' bits through a field of -		 * '0's and '0' bits through a field of '1's (i.e. -		 * pattern and ~pattern). -		 */ -		addr = start; -		for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) { -		    val = bitpattern[j]; -		    for(; val != 0; val <<= 1) { -			*addr  = val; -			*dummy  = ~val; /* clear the test data off of the bus */ +	/* +	 * Data line test: write a pattern to the first +	 * location, write the 1's complement to a 'parking' +	 * address (changes the state of the data bus so a +	 * floating bus doesn't give a false OK), and then +	 * read the value back. Note that we read it back +	 * into a variable because the next time we read it, +	 * it might be right (been there, tough to explain to +	 * the quality guys why it prints a failure when the +	 * "is" and "should be" are obviously the same in the +	 * error message). +	 * +	 * Rather than exhaustively testing, we test some +	 * patterns by shifting '1' bits through a field of +	 * '0's and '0' bits through a field of '1's (i.e. +	 * pattern and ~pattern). +	 */ +	addr = buf; +	for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) { +		val = bitpattern[j]; +		for (; val != 0; val <<= 1) { +			*addr = val; +			*dummy  = ~val; /* clear the test data off the bus */  			readback = *addr; -			if(readback != val) { -			    printf ("FAILURE (data line): " -				"expected %08lx, actual %08lx\n", -					  val, readback); -			    errs++; -			    if (ctrlc()) { -				putc ('\n'); -				return 1; -			    } +			if (readback != val) { +				printf("FAILURE (data line): " +					"expected %08lx, actual %08lx\n", +						val, readback); +				errs++; +				if (ctrlc()) +					return -1;  			}  			*addr  = ~val;  			*dummy  = val;  			readback = *addr; -			if(readback != ~val) { -			    printf ("FAILURE (data line): " -				"Is %08lx, should be %08lx\n", -					readback, ~val); -			    errs++; -			    if (ctrlc()) { -				putc ('\n'); -				return 1; -			    } +			if (readback != ~val) { +				printf("FAILURE (data line): " +					"Is %08lx, should be %08lx\n", +						readback, ~val); +				errs++; +				if (ctrlc()) +					return -1;  			} -		    }  		} +	} -		/* -		 * Based on code whose Original Author and Copyright -		 * information follows: Copyright (c) 1998 by Michael -		 * Barr. This software is placed into the public -		 * domain and may be used for any purpose. However, -		 * this notice must not be changed or removed and no -		 * warranty is either expressed or implied by its -		 * publication or distribution. -		 */ +	/* +	 * Based on code whose Original Author and Copyright +	 * information follows: Copyright (c) 1998 by Michael +	 * Barr. This software is placed into the public +	 * domain and may be used for any purpose. However, +	 * this notice must not be changed or removed and no +	 * warranty is either expressed or implied by its +	 * publication or distribution. +	 */ -		/* -		 * Address line test -		 * -		 * Description: Test the address bus wiring in a -		 *              memory region by performing a walking -		 *              1's test on the relevant bits of the -		 *              address and checking for aliasing. -		 *              This test will find single-bit -		 *              address failures such as stuck -high, -		 *              stuck-low, and shorted pins. The base -		 *              address and size of the region are -		 *              selected by the caller. -		 * -		 * Notes:	For best results, the selected base -		 *              address should have enough LSB 0's to -		 *              guarantee single address bit changes. -		 *              For example, to test a 64-Kbyte -		 *              region, select a base address on a -		 *              64-Kbyte boundary. Also, select the -		 *              region size as a power-of-two if at -		 *              all possible. -		 * -		 * Returns:     0 if the test succeeds, 1 if the test fails. -		 */ -		len = ((ulong)end - (ulong)start)/sizeof(vu_long); -		pattern = (vu_long) 0xaaaaaaaa; -		anti_pattern = (vu_long) 0x55555555; +	/* +	* Address line test -		debug("%s:%d: length = 0x%.8lx\n", -			__FUNCTION__, __LINE__, -			len); -		/* -		 * Write the default pattern at each of the -		 * power-of-two offsets. -		 */ -		for (offset = 1; offset < len; offset <<= 1) { -			start[offset] = pattern; -		} +	 * Description: Test the address bus wiring in a +	 *              memory region by performing a walking +	 *              1's test on the relevant bits of the +	 *              address and checking for aliasing. +	 *              This test will find single-bit +	 *              address failures such as stuck-high, +	 *              stuck-low, and shorted pins. The base +	 *              address and size of the region are +	 *              selected by the caller. -		/* -		 * Check for address bits stuck high. -		 */ -		test_offset = 0; -		start[test_offset] = anti_pattern; +	 * Notes:	For best results, the selected base +	 *              address should have enough LSB 0's to +	 *              guarantee single address bit changes. +	 *              For example, to test a 64-Kbyte +	 *              region, select a base address on a +	 *              64-Kbyte boundary. Also, select the +	 *              region size as a power-of-two if at +	 *              all possible. +	 * +	 * Returns:     0 if the test succeeds, 1 if the test fails. +	 */ +	pattern = (vu_long) 0xaaaaaaaa; +	anti_pattern = (vu_long) 0x55555555; + +	debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words); +	/* +	 * Write the default pattern at each of the +	 * power-of-two offsets. +	 */ +	for (offset = 1; offset < num_words; offset <<= 1) +		addr[offset] = pattern; + +	/* +	 * Check for address bits stuck high. +	 */ +	test_offset = 0; +	addr[test_offset] = anti_pattern; -		for (offset = 1; offset < len; offset <<= 1) { -		    temp = start[offset]; -		    if (temp != pattern) { -			printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:" +	for (offset = 1; offset < num_words; offset <<= 1) { +		temp = addr[offset]; +		if (temp != pattern) { +			printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"  				" expected 0x%.8lx, actual 0x%.8lx\n", -				(ulong)&start[offset], pattern, temp); +				start_addr + offset, pattern, temp);  			errs++; -			if (ctrlc()) { -			    putc ('\n'); -			    return 1; -			} -		    } +			if (ctrlc()) +				return -1;  		} -		start[test_offset] = pattern; -		WATCHDOG_RESET(); +	} +	addr[test_offset] = pattern; +	WATCHDOG_RESET(); -		/* -		 * Check for addr bits stuck low or shorted. -		 */ -		for (test_offset = 1; test_offset < len; test_offset <<= 1) { -		    start[test_offset] = anti_pattern; +	/* +	 * Check for addr bits stuck low or shorted. +	 */ +	for (test_offset = 1; test_offset < num_words; test_offset <<= 1) { +		addr[test_offset] = anti_pattern; -		    for (offset = 1; offset < len; offset <<= 1) { -			temp = start[offset]; +		for (offset = 1; offset < num_words; offset <<= 1) { +			temp = addr[offset];  			if ((temp != pattern) && (offset != test_offset)) { -			    printf ("\nFAILURE: Address bit stuck low or shorted @" -				" 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n", -				(ulong)&start[offset], pattern, temp); -			    errs++; -			    if (ctrlc()) { -				putc ('\n'); -				return 1; -			    } +				printf("\nFAILURE: Address bit stuck low or" +					" shorted @ 0x%.8lx: expected 0x%.8lx," +					" actual 0x%.8lx\n", +					start_addr + offset, pattern, temp); +				errs++; +				if (ctrlc()) +					return -1;  			} -		    } -		    start[test_offset] = pattern;  		} +		addr[test_offset] = pattern; +	} -		/* -		 * Description: Test the integrity of a physical -		 *		memory device by performing an -		 *		increment/decrement test over the -		 *		entire region. In the process every -		 *		storage bit in the device is tested -		 *		as a zero and a one. The base address -		 *		and the size of the region are -		 *		selected by the caller. -		 * -		 * Returns:     0 if the test succeeds, 1 if the test fails. -		 */ -		num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1; +	/* +	 * Description: Test the integrity of a physical +	 *		memory device by performing an +	 *		increment/decrement test over the +	 *		entire region. In the process every +	 *		storage bit in the device is tested +	 *		as a zero and a one. The base address +	 *		and the size of the region are +	 *		selected by the caller. +	 * +	 * Returns:     0 if the test succeeds, 1 if the test fails. +	 */ +	num_words++; -		/* -		 * Fill memory with a known pattern. -		 */ -		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { -			WATCHDOG_RESET(); -			start[offset] = pattern; -		} +	/* +	 * Fill memory with a known pattern. +	 */ +	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { +		WATCHDOG_RESET(); +		addr[offset] = pattern; +	} -		/* -		 * Check each location and invert it for the second pass. -		 */ -		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { -		    WATCHDOG_RESET(); -		    temp = start[offset]; -		    if (temp != pattern) { -			printf ("\nFAILURE (read/write) @ 0x%.8lx:" +	/* +	 * Check each location and invert it for the second pass. +	 */ +	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { +		WATCHDOG_RESET(); +		temp = addr[offset]; +		if (temp != pattern) { +			printf("\nFAILURE (read/write) @ 0x%.8lx:"  				" expected 0x%.8lx, actual 0x%.8lx)\n", -				(ulong)&start[offset], pattern, temp); +				start_addr + offset, pattern, temp);  			errs++; -			if (ctrlc()) { -			    putc ('\n'); -			    return 1; -			} -		    } - -		    anti_pattern = ~pattern; -		    start[offset] = anti_pattern; +			if (ctrlc()) +				return -1;  		} -		/* -		 * Check each location for the inverted pattern and zero it. -		 */ -		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { -		    WATCHDOG_RESET(); -		    anti_pattern = ~pattern; -		    temp = start[offset]; -		    if (temp != anti_pattern) { -			printf ("\nFAILURE (read/write): @ 0x%.8lx:" +		anti_pattern = ~pattern; +		addr[offset] = anti_pattern; +	} + +	/* +	 * Check each location for the inverted pattern and zero it. +	 */ +	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { +		WATCHDOG_RESET(); +		anti_pattern = ~pattern; +		temp = addr[offset]; +		if (temp != anti_pattern) { +			printf("\nFAILURE (read/write): @ 0x%.8lx:"  				" expected 0x%.8lx, actual 0x%.8lx)\n", -				(ulong)&start[offset], anti_pattern, temp); +				start_addr + offset, anti_pattern, temp);  			errs++; -			if (ctrlc()) { -			    putc ('\n'); -			    return 1; -			} -		    } -		    start[offset] = 0; +			if (ctrlc()) +				return -1;  		} +		addr[offset] = 0;  	} -#else /* The original, quickie test */ -	incr = 1; -	for (;;) { -		if (ctrlc()) { -			putc ('\n'); -			return 1; -		} - -		if (iteration_limit && iterations > iteration_limit) { -			printf("Tested %d iteration(s) with %lu errors.\n", -				iterations-1, errs); -			return errs != 0; -		} -		++iterations; - -		printf ("\rPattern %08lX  Writing..." -			"%12s" -			"\b\b\b\b\b\b\b\b\b\b", -			pattern, ""); - -		for (addr=start,val=pattern; addr<end; addr++) { -			WATCHDOG_RESET(); -			*addr = val; -			val  += incr; -		} - -		puts ("Reading..."); +	return 0; +} -		for (addr=start,val=pattern; addr<end; addr++) { -			WATCHDOG_RESET(); -			readback = *addr; -			if (readback != val) { -				printf ("\nMem error @ 0x%08X: " -					"found %08lX, expected %08lX\n", -					(uint)(uintptr_t)addr, readback, val); -				errs++; -				if (ctrlc()) { -					putc ('\n'); -					return 1; -				} -			} -			val += incr; -		} +static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr, +			    vu_long pattern, int iteration) +{ +	vu_long *end; +	vu_long *addr; +	ulong errs = 0; +	ulong incr, length; +	ulong val, readback; +	/* Alternate the pattern */ +	incr = 1; +	if (iteration & 1) { +		incr = -incr;  		/*  		 * Flip the pattern each time to make lots of zeros and  		 * then, the next time, lots of ones.  We decrement  		 * the "negative" patterns and increment the "positive"  		 * patterns to preserve this feature.  		 */ -		if(pattern & 0x80000000) { +		if (pattern & 0x80000000)  			pattern = -pattern;	/* complement & increment */ -		} -		else { +		else  			pattern = ~pattern; +	} +	length = (end_addr - start_addr) / sizeof(ulong); +	end = buf + length; +	printf("\rPattern %08lX  Writing..." +		"%12s" +		"\b\b\b\b\b\b\b\b\b\b", +		pattern, ""); + +	for (addr = buf, val = pattern; addr < end; addr++) { +		WATCHDOG_RESET(); +		*addr = val; +		val += incr; +	} + +	puts("Reading..."); + +	for (addr = buf, val = pattern; addr < end; addr++) { +		WATCHDOG_RESET(); +		readback = *addr; +		if (readback != val) { +			ulong offset = addr - buf; + +			printf("\nMem error @ 0x%08X: " +				"found %08lX, expected %08lX\n", +				(uint)(uintptr_t)(start_addr + offset), +				readback, val); +			errs++; +			if (ctrlc()) +				return -1;  		} -		incr = -incr; +		val += incr;  	} + +	return 0; +} + +/* + * Perform a memory test. A more complete alternative test can be + * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until + * interrupted by ctrl-c or by a failure of one of the sub-tests. + */ +static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, +			char * const argv[]) +{ +	ulong start, end; +	vu_long *buf, *dummy; +	int iteration_limit; +	int ret; +	ulong errs = 0;	/* number of errors, or -1 if interrupted */ +	ulong pattern; +	int iteration; +#if defined(CONFIG_SYS_ALT_MEMTEST) +	const int alt_test = 1; +#else +	const int alt_test = 0;  #endif -	return 0;	/* not reached */ + +	if (argc > 1) +		start = simple_strtoul(argv[1], NULL, 16); +	else +		start = CONFIG_SYS_MEMTEST_START; + +	if (argc > 2) +		end = simple_strtoul(argv[2], NULL, 16); +	else +		end = CONFIG_SYS_MEMTEST_END; + +	if (argc > 3) +		pattern = (ulong)simple_strtoul(argv[3], NULL, 16); +	else +		pattern = 0; + +	if (argc > 4) +		iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16); +	else +		iteration_limit = 0; + +	printf("Testing %08x ... %08x:\n", (uint)start, (uint)end); +	debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__, +	      start, end); + +	buf = map_sysmem(start, end - start); +	dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long)); +	for (iteration = 0; +			!iteration_limit || iteration < iteration_limit; +			iteration++) { +		if (ctrlc()) { +			errs = -1UL; +			break; +		} + +		printf("Iteration: %6d\r", iteration + 1); +		debug("\n"); +		if (alt_test) { +			errs = mem_test_alt(buf, start, end, dummy); +		} else { +			errs = mem_test_quick(buf, start, end, pattern, +					      iteration); +		} +		if (errs == -1UL) +			break; +	} + +	/* +	 * Work-around for eldk-4.2 which gives this warning if we try to +	 * case in the unmap_sysmem() call: +	 * warning: initialization discards qualifiers from pointer target type +	 */ +	{ +		void *vbuf = (void *)buf; +		void *vdummy = (void *)dummy; + +		unmap_sysmem(vbuf); +		unmap_sysmem(vdummy); +	} + +	if (errs == -1UL) { +		/* Memory test was aborted - write a newline to finish off */ +		putc('\n'); +		ret = 1; +	} else { +		printf("Tested %d iteration(s) with %lu errors.\n", +			iteration, errs); +		ret = errs != 0; +	} + +	return ret;	/* not reached */  } @@ -960,6 +1015,7 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])  {  	ulong	addr, i;  	int	nbytes, size; +	void *ptr = NULL;  	if (argc != 2)  		return CMD_RET_USAGE; @@ -1004,13 +1060,14 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])  	 * the next value.  A non-converted value exits.  	 */  	do { +		ptr = map_sysmem(addr, size);  		printf("%08lx:", addr);  		if (size == 4) -			printf(" %08x", *((uint   *)addr)); +			printf(" %08x", *((uint *)ptr));  		else if (size == 2) -			printf(" %04x", *((ushort *)addr)); +			printf(" %04x", *((ushort *)ptr));  		else -			printf(" %02x", *((u_char *)addr)); +			printf(" %02x", *((u_char *)ptr));  		nbytes = readline (" ? ");  		if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { @@ -1040,16 +1097,18 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])  				reset_cmd_timeout();  #endif  				if (size == 4) -					*((uint   *)addr) = i; +					*((uint *)ptr) = i;  				else if (size == 2) -					*((ushort *)addr) = i; +					*((ushort *)ptr) = i;  				else -					*((u_char *)addr) = i; +					*((u_char *)ptr) = i;  				if (incrflag)  					addr += size;  			}  		}  	} while (nbytes); +	if (ptr) +		unmap_sysmem(ptr);  	mm_last_addr = addr;  	mm_last_size = size; @@ -1058,89 +1117,27 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])  #ifdef CONFIG_CMD_CRC32 -#ifndef CONFIG_CRC32_VERIFY -  static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  { -	ulong addr, length; -	ulong crc; -	ulong *ptr; - -	if (argc < 3) -		return CMD_RET_USAGE; - -	addr = simple_strtoul (argv[1], NULL, 16); -	addr += base_address; - -	length = simple_strtoul (argv[2], NULL, 16); - -	crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32); - -	printf ("CRC32 for %08lx ... %08lx ==> %08lx\n", -			addr, addr + length - 1, crc); - -	if (argc > 3) { -		ptr = (ulong *) simple_strtoul (argv[3], NULL, 16); -		*ptr = crc; -	} - -	return 0; -} - -#else	/* CONFIG_CRC32_VERIFY */ - -int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ -	ulong addr, length; -	ulong crc; -	ulong *ptr; -	ulong vcrc; -	int verify; +	int flags = 0;  	int ac;  	char * const *av; -	if (argc < 3) { -usage: +	if (argc < 3)  		return CMD_RET_USAGE; -	}  	av = argv + 1;  	ac = argc - 1; +#ifdef CONFIG_HASH_VERIFY  	if (strcmp(*av, "-v") == 0) { -		verify = 1; +		flags |= HASH_FLAG_VERIFY;  		av++;  		ac--; -		if (ac < 3) -			goto usage; -	} else -		verify = 0; - -	addr = simple_strtoul(*av++, NULL, 16); -	addr += base_address; -	length = simple_strtoul(*av++, NULL, 16); - -	crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32); - -	if (!verify) { -		printf ("CRC32 for %08lx ... %08lx ==> %08lx\n", -				addr, addr + length - 1, crc); -		if (ac > 2) { -			ptr = (ulong *) simple_strtoul (*av++, NULL, 16); -			*ptr = crc; -		} -	} else { -		vcrc = simple_strtoul(*av++, NULL, 16); -		if (vcrc != crc) { -			printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n", -					addr, addr + length - 1, crc, vcrc); -			return 1; -		}  	} +#endif -	return 0; - +	return hash_command("crc32", flags, cmdtp, flag, ac, av);  } -#endif	/* CONFIG_CRC32_VERIFY */  #endif diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 7dacd5114..8c53a1031 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -282,6 +282,13 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		mmc_init(mmc); +		if ((state == MMC_WRITE || state == MMC_ERASE)) { +			if (mmc_getwp(mmc) == 1) { +				printf("Error: card is write protected!\n"); +				return 1; +			} +		} +  		switch (state) {  		case MMC_READ:  			n = mmc->block_dev.block_read(curr_device, blk, diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 06fc171fe..0cfca0c46 100644 --- a/common/cmd_mtdparts.c +++ b/common/cmd_mtdparts.c @@ -230,7 +230,6 @@ static void memsize_format(char *buf, u32 size)   */  static void index_partitions(void)  { -	char buf[16];  	u16 mtddevnum;  	struct part_info *part;  	struct list_head *dentry; @@ -244,8 +243,7 @@ static void index_partitions(void)  			dev = list_entry(dentry, struct mtd_device, link);  			if (dev == current_mtd_dev) {  				mtddevnum += current_mtd_partnum; -				sprintf(buf, "%d", mtddevnum); -				setenv("mtddevnum", buf); +				setenv_ulong("mtddevnum", mtddevnum);  				break;  			}  			mtddevnum += dev->num_parts; diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 1568594ca..32348f377 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -373,7 +373,6 @@ static void nand_print_and_set_info(int idx)  {  	nand_info_t *nand = &nand_info[idx];  	struct nand_chip *chip = nand->priv; -	char buf[32];  	printf("Device %d: ", idx);  	if (chip->numchips > 1) @@ -385,14 +384,9 @@ static void nand_print_and_set_info(int idx)  	printf("  Erase size %8d b\n", nand->erasesize);  	/* Set geometry info */ -	sprintf(buf, "%x", nand->writesize); -	setenv("nand_writesize", buf); - -	sprintf(buf, "%x", nand->oobsize); -	setenv("nand_oobsize", buf); - -	sprintf(buf, "%x", nand->erasesize); -	setenv("nand_erasesize", buf); +	setenv_hex("nand_writesize", nand->writesize); +	setenv_hex("nand_oobsize", nand->oobsize); +	setenv_hex("nand_erasesize", nand->erasesize);  }  static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, @@ -608,7 +602,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		size_t rwsize;  		ulong pagecount = 1;  		int read; -		int raw; +		int raw = 0;  		if (argc < 4)  			goto usage; diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 7633f0c44..3a05e6010 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -295,17 +295,17 @@ int setenv_ulong(const char *varname, ulong value)  }  /** - * Set an environment variable to an address in hex + * Set an environment variable to an value in hex   *   * @param varname	Environmet variable to set - * @param addr		Value to set it to + * @param value		Value to set it to   * @return 0 if ok, 1 on error   */ -int setenv_addr(const char *varname, const void *addr) +int setenv_hex(const char *varname, ulong value)  {  	char str[17]; -	sprintf(str, "%lx", (uintptr_t)addr); +	sprintf(str, "%lx", value);  	return setenv(varname, str);  } @@ -552,7 +552,8 @@ static int do_env_edit(cmd_tbl_t *cmdtp, int flag, int argc,  	else  		buffer[0] = '\0'; -	readline_into_buffer("edit: ", buffer, 0); +	if (readline_into_buffer("edit: ", buffer, 0) < 0) +		return 1;  	return setenv(argv[1], buffer);  } @@ -891,8 +892,7 @@ NXTARG:		;  		envp->flags = ACTIVE_FLAG;  #endif  	} -	sprintf(buf, "%zX", (size_t)(len + offsetof(env_t, data))); -	setenv("filesize", buf); +	setenv_hex("filesize", len + offsetof(env_t, data));  	return 0; diff --git a/common/cmd_reginfo.c b/common/cmd_reginfo.c index 08a656344..b591bd377 100644 --- a/common/cmd_reginfo.c +++ b/common/cmd_reginfo.c @@ -191,7 +191,7 @@ static int do_reginfo(cmd_tbl_t *cmdtp, int flag, int argc,  #elif defined(CONFIG_BLACKFIN)  	puts("\nSystem Configuration registers\n"); - +#ifndef __ADSPBF60x__  	puts("\nPLL Registers\n");  	printf("\tPLL_DIV:   0x%04x   PLL_CTL:      0x%04x\n",  		bfin_read_PLL_DIV(), bfin_read_PLL_CTL()); @@ -227,7 +227,24 @@ static int do_reginfo(cmd_tbl_t *cmdtp, int flag, int argc,  	printf("\tEBIU_SDSTAT:  0x%04x   EBIU_SDGCTL:  0x%08x\n",  		bfin_read_EBIU_SDSTAT(), bfin_read_EBIU_SDGCTL());  # endif +#else +	puts("\nCGU Registers\n"); +	printf("\tCGU_DIV:   0x%08x   CGU_CTL:      0x%08x\n", +		bfin_read_CGU_DIV(), bfin_read_CGU_CTL()); +	printf("\tCGU_STAT:  0x%08x   CGU_LOCKCNT:  0x%08x\n", +		bfin_read_CGU_STAT(), bfin_read_CGU_CLKOUTSEL()); +	puts("\nSMC DDR Registers\n"); +	printf("\tDDR_CFG:   0x%08x   DDR_TR0:      0x%08x\n", +		bfin_read_DMC0_CFG(), bfin_read_DMC0_TR0()); +	printf("\tDDR_TR1:   0x%08x   DDR_TR2:      0x%08x\n", +		bfin_read_DMC0_TR1(), bfin_read_DMC0_TR2()); +	printf("\tDDR_MR:    0x%08x   DDR_EMR1:     0x%08x\n", +		bfin_read_DMC0_MR(), bfin_read_DMC0_EMR1()); +	printf("\tDDR_CTL:   0x%08x   DDR_STAT:     0x%08x\n", +		bfin_read_DMC0_CTL(), bfin_read_DMC0_STAT()); +	printf("\tDDR_DLLCTL:0x%08x\n", bfin_read_DMC0_DLLCTL()); +#endif  #endif /* CONFIG_BLACKFIN */  	return 0; diff --git a/common/cmd_reiser.c b/common/cmd_reiser.c index e658618c6..717c7f657 100644 --- a/common/cmd_reiser.c +++ b/common/cmd_reiser.c @@ -100,7 +100,6 @@ int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	ulong addr = 0, filelen;  	disk_partition_t info;  	block_dev_desc_t *dev_desc = NULL; -	char buf [12];  	unsigned long count;  	char *addr_str; @@ -175,8 +174,7 @@ int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	load_addr = addr;  	printf ("\n%ld bytes read\n", filelen); -	sprintf(buf, "%lX", filelen); -	setenv("filesize", buf); +	setenv_hex("filesize", filelen);  	return filelen;  } diff --git a/common/cmd_sandbox.c b/common/cmd_sandbox.c new file mode 100644 index 000000000..206a48614 --- /dev/null +++ b/common/cmd_sandbox.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, Google Inc. + * + * 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 <fs.h> + +static int do_sandbox_load(cmd_tbl_t *cmdtp, int flag, int argc, +			   char * const argv[]) +{ +	return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX, 16); +} + +static int do_sandbox_ls(cmd_tbl_t *cmdtp, int flag, int argc, +			   char * const argv[]) +{ +	return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static cmd_tbl_t cmd_sandbox_sub[] = { +	U_BOOT_CMD_MKENT(load, 3, 0, do_sandbox_load, "", ""), +	U_BOOT_CMD_MKENT(ls, 3, 0, do_sandbox_ls, "", ""), +}; + +static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, +		      char * const argv[]) +{ +	cmd_tbl_t *c; + +	/* Skip past 'sandbox' */ +	argc--; +	argv++; + +	c = find_cmd_tbl(argv[0], cmd_sandbox_sub, +			 ARRAY_SIZE(cmd_sandbox_sub)); + +	if (c) +		return c->cmd(cmdtp, flag, argc, argv); +	else +		return CMD_RET_USAGE; +} + +U_BOOT_CMD( +	sb,	6,	1,	do_sandbox, +	"Miscellaneous sandbox commands", +	"load host <addr> <filename> [<bytes> <offset>]  - load a file from host\n" +	"sb ls host <filename>      - save a file to host" +); diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c index 5a042951d..7a38e9450 100644 --- a/common/cmd_setexpr.c +++ b/common/cmd_setexpr.c @@ -53,7 +53,7 @@ static ulong get_arg(char *s, int w)  static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	ulong a, b; -	char buf[16]; +	ulong value;  	int w;  	/* Validate arguments */ @@ -67,8 +67,7 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	a = get_arg(argv[2], w);  	if (argc == 3) { -		sprintf(buf, "%lx", a); -		setenv(argv[1], buf); +		setenv_hex(argv[1], a);  		return 0;  	} @@ -76,20 +75,36 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	b = get_arg(argv[4], w);  	switch (argv[3][0]) { -	case '|': sprintf(buf, "%lx", (a | b)); break; -	case '&': sprintf(buf, "%lx", (a & b)); break; -	case '+': sprintf(buf, "%lx", (a + b)); break; -	case '^': sprintf(buf, "%lx", (a ^ b)); break; -	case '-': sprintf(buf, "%lx", (a - b)); break; -	case '*': sprintf(buf, "%lx", (a * b)); break; -	case '/': sprintf(buf, "%lx", (a / b)); break; -	case '%': sprintf(buf, "%lx", (a % b)); break; +	case '|': +		value = a | b; +		break; +	case '&': +		value = a & b; +		break; +	case '+': +		value = a + b; +		break; +	case '^': +		value = a ^ b; +		break; +	case '-': +		value = a - b; +		break; +	case '*': +		value = a * b; +		break; +	case '/': +		value = a / b; +		break; +	case '%': +		value = a % b; +		break;  	default:  		printf("invalid op\n");  		return 1;  	} -	setenv(argv[1], buf); +	setenv_hex(argv[1], value);  	return 0;  } diff --git a/common/cmd_sha1sum.c b/common/cmd_sha1sum.c index fe927ab24..9f08629b8 100644 --- a/common/cmd_sha1sum.c +++ b/common/cmd_sha1sum.c @@ -31,7 +31,7 @@  int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  { -	int verify = 0; +	int flags = HASH_FLAG_ENV;  	int ac;  	char * const *av; @@ -42,13 +42,13 @@ int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	ac = argc - 1;  #ifdef CONFIG_SHA1SUM_VERIFY  	if (strcmp(*av, "-v") == 0) { -		verify = 1; +		flags |= HASH_FLAG_VERIFY;  		av++;  		ac--;  	}  #endif -	return hash_command("sha1", verify, cmdtp, flag, ac, av); +	return hash_command("sha1", flags, cmdtp, flag, ac, av);  }  #ifdef CONFIG_SHA1SUM_VERIFY diff --git a/common/cmd_spl.c b/common/cmd_spl.c index e3c543b46..94b0a1715 100644 --- a/common/cmd_spl.c +++ b/common/cmd_spl.c @@ -184,7 +184,11 @@ static int do_spl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  U_BOOT_CMD(  	spl, 6 , 1, do_spl, "SPL configuration", -	"export <img=atags|fdt> [kernel_addr] [initrd_addr] " -	"[fdt_addr if <img> = fdt] - export a kernel parameter image\n" -	"\t initrd_img can be set to \"-\" if fdt_addr without initrd img is" -	"used"); +	"export <img=atags|fdt> [kernel_addr] [initrd_addr] [fdt_addr]\n" +	"\timg\t\t\"atags\" or \"fdt\"\n" +	"\tkernel_addr\taddress where a kernel image is stored.\n" +	"\t\t\tkernel is loaded as part of the boot process, but it is not started.\n" +	"\tinitrd_addr\taddress of initial ramdisk\n" +	"\t\t\tcan be set to \"-\" if fdt_addr without initrd_addr is used.\n" +	"\tfdt_addr\tin case of fdt, the address of the device tree.\n" +	); diff --git a/common/cmd_unzip.c b/common/cmd_unzip.c index 43ed7915f..7470c2b12 100644 --- a/common/cmd_unzip.c +++ b/common/cmd_unzip.c @@ -28,7 +28,6 @@ static int do_unzip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	unsigned long src, dst;  	unsigned long src_len = ~0UL, dst_len = ~0UL; -	char buf[32];  	switch (argc) {  		case 4: @@ -46,8 +45,7 @@ static int do_unzip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		return 1;  	printf("Uncompressed size: %ld = 0x%lX\n", src_len, src_len); -	sprintf(buf, "%lX", src_len); -	setenv("filesize", buf); +	setenv_hex("filesize", src_len);  	return 0;  } diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 42a7eba76..ea0a26e78 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -50,7 +50,6 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  	ulong		data, len, count;  	int		verify;  	int		part = 0; -	char		pbuf[10];  	image_header_t	*hdr;  #if defined(CONFIG_FIT)  	const char	*uname = NULL; @@ -256,10 +255,8 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		puts("OK\n");  	} -	sprintf(pbuf, "%8lx", data); -	setenv("fileaddr", pbuf); -	sprintf(pbuf, "%8lx", len); -	setenv("filesize", pbuf); +	setenv_hex("fileaddr", data); +	setenv_hex("filesize", len);  	return 0;  } diff --git a/common/cmd_zfs.c b/common/cmd_zfs.c index 1df0c4d72..900e977c1 100644 --- a/common/cmd_zfs.c +++ b/common/cmd_zfs.c @@ -129,8 +129,7 @@ static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]  	load_addr = addr;  	printf("%llu bytes read\n", zfile.size); -	sprintf(buf, "%llX", zfile.size); -	setenv("filesize", buf); +	setenv_hex("filesize", zfile.size);  	return 0;  } diff --git a/common/cmd_zip.c b/common/cmd_zip.c index a73c86d59..8607da81e 100644 --- a/common/cmd_zip.c +++ b/common/cmd_zip.c @@ -28,7 +28,6 @@ static int do_zip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	unsigned long src, dst;  	unsigned long src_len, dst_len = ~0UL; -	char buf[32];  	switch (argc) {  		case 5: @@ -47,8 +46,7 @@ static int do_zip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		return 1;  	printf("Compressed size: %ld = 0x%lX\n", dst_len, dst_len); -	sprintf(buf, "%lX", dst_len); -	setenv("filesize", buf); +	setenv_hex("filesize", dst_len);  	return 0;  } diff --git a/common/dlmalloc.c b/common/dlmalloc.c index b2f0a1ad5..2a9d169f9 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1485,7 +1485,7 @@ static mbinptr av_[NAV * 2 + 2] = {  };  #ifdef CONFIG_NEEDS_MANUAL_RELOC -void malloc_bin_reloc (void) +static void malloc_bin_reloc(void)  {  	mbinptr *p = &av_[2];  	size_t i; @@ -1493,6 +1493,8 @@ void malloc_bin_reloc (void)  	for (i = 2; i < ARRAY_SIZE(av_); ++i, ++p)  		*p = (mbinptr)((ulong)*p + gd->reloc_off);  } +#else +static inline void malloc_bin_reloc(void) {}  #endif  ulong mem_malloc_start = 0; @@ -1526,6 +1528,8 @@ void mem_malloc_init(ulong start, ulong size)  	mem_malloc_brk = start;  	memset((void *)mem_malloc_start, 0, size); + +	malloc_bin_reloc();  }  /* field-extraction macros */ diff --git a/common/env_nand.c b/common/env_nand.c index 22e72a20b..5b69889c0 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -331,6 +331,7 @@ int get_nand_env_oob(nand_info_t *nand, unsigned long *result)  void env_relocate_spec(void)  {  #if !defined(ENV_IS_EMBEDDED) +	int read1_fail = 0, read2_fail = 0;  	int crc1_ok = 0, crc2_ok = 0;  	env_t *ep, *tmp_env1, *tmp_env2; @@ -342,14 +343,19 @@ void env_relocate_spec(void)  		goto done;  	} -	if (readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1)) -		puts("No Valid Environment Area found\n"); +	read1_fail = readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1); +	read2_fail = readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2); -	if (readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2)) -		puts("No Valid Redundant Environment Area found\n"); +	if (read1_fail && read2_fail) +		puts("*** Error - No Valid Environment Area found\n"); +	else if (read1_fail || read2_fail) +		puts("*** Warning - some problems detected " +		     "reading environment; recovered successfully\n"); -	crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc; -	crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc; +	crc1_ok = !read1_fail && +		(crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); +	crc2_ok = !read2_fail && +		(crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);  	if (!crc1_ok && !crc2_ok) {  		set_default_env("!bad CRC"); diff --git a/common/hash.c b/common/hash.c index e3a6e438a..f5badcb93 100644 --- a/common/hash.c +++ b/common/hash.c @@ -28,49 +28,87 @@  #include <hash.h>  #include <sha1.h>  #include <sha256.h> +#include <asm/io.h>  /*   * These are the hash algorithms we support. Chips which support accelerated - * crypto could perhaps add named version of these algorithms here. + * crypto could perhaps add named version of these algorithms here. Note that + * algorithm names must be in lower case.   */  static struct hash_algo hash_algo[] = { -#ifdef CONFIG_SHA1 +	/* +	 * This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise +	 * it bloats the code for boards which use SHA1 but not the 'hash' +	 * or 'sha1sum' commands. +	 */ +#ifdef CONFIG_CMD_SHA1SUM  	{ -		"SHA1", +		"sha1",  		SHA1_SUM_LEN,  		sha1_csum_wd,  		CHUNKSZ_SHA1,  	}, +#define MULTI_HASH  #endif  #ifdef CONFIG_SHA256  	{ -		"SHA256", +		"sha256",  		SHA256_SUM_LEN,  		sha256_csum_wd,  		CHUNKSZ_SHA256,  	}, +#define MULTI_HASH  #endif +	{ +		"crc32", +		4, +		crc32_wd_buf, +		CHUNKSZ_CRC32, +	},  }; +#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH) +#define MULTI_HASH +#endif + +/* Try to minimize code size for boards that don't want much hashing */ +#ifdef MULTI_HASH +#define multi_hash()	1 +#else +#define multi_hash()	0 +#endif +  /**   * store_result: Store the resulting sum to an address or variable   *   * @algo:		Hash algorithm being used   * @sum:		Hash digest (algo->digest_size bytes)   * @dest:		Destination, interpreted as a hex address if it starts - *			with * or otherwise as an environment variable. + *			with * (or allow_env_vars is 0) or otherwise as an + *			environment variable. + * @allow_env_vars:	non-zero to permit storing the result to an + *			variable environment   */  static void store_result(struct hash_algo *algo, const u8 *sum, -			 const char *dest) +			 const char *dest, int allow_env_vars)  {  	unsigned int i; +	int env_var = 0; -	if (*dest == '*') { -		u8 *ptr; +	/* +	 * If environment variables are allowed, then we assume that 'dest' +	 * is an environment variable, unless it starts with *, in which +	 * case we assume it is an address. If not allowed, it is always an +	 * address. This is to support the crc32 command. +	 */ +	if (allow_env_vars) { +		if (*dest == '*') +			dest++; +		else +			env_var = 1; +	} -		ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16); -		memcpy(ptr, sum, algo->digest_size); -	} else { +	if (env_var) {  		char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];  		char *str_ptr = str_output; @@ -80,6 +118,14 @@ static void store_result(struct hash_algo *algo, const u8 *sum,  		}  		str_ptr = '\0';  		setenv(dest, str_output); +	} else { +		ulong addr; +		void *buf; + +		addr = simple_strtoul(dest, NULL, 16); +		buf = map_sysmem(addr, algo->digest_size); +		memcpy(buf, sum, algo->digest_size); +		unmap_sysmem(buf);  	}  } @@ -94,15 +140,31 @@ static void store_result(struct hash_algo *algo, const u8 *sum,   *			Otherwise we assume it is an environment variable, and   *			look up its value (it must contain a hex digest).   * @vsum:		Returns binary digest value (algo->digest_size bytes) + * @allow_env_vars:	non-zero to permit storing the result to an environment + *			variable. If 0 then verify_str is assumed to be an + *			address, and the * prefix is not expected.   * @return 0 if ok, non-zero on error   */ -static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum) +static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum, +			    int allow_env_vars)  { -	if (*verify_str == '*') { -		u8 *ptr; +	int env_var = 0; + +	/* See comment above in store_result() */ +	if (allow_env_vars) { +		if (*verify_str == '*') +			verify_str++; +		else +			env_var = 1; +	} -		ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16); -		memcpy(vsum, ptr, algo->digest_size); +	if (env_var) { +		ulong addr; +		void *buf; + +		addr = simple_strtoul(verify_str, NULL, 16); +		buf = map_sysmem(addr, algo->digest_size); +		memcpy(vsum, buf, algo->digest_size);  	} else {  		unsigned int i;  		char *vsum_str; @@ -141,7 +203,7 @@ static struct hash_algo *find_hash_algo(const char *name)  	int i;  	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { -		if (!strcasecmp(name, hash_algo[i].name)) +		if (!strcmp(name, hash_algo[i].name))  			return &hash_algo[i];  	} @@ -158,63 +220,87 @@ static void show_hash(struct hash_algo *algo, ulong addr, ulong len,  		printf("%02x", output[i]);  } -int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, +int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,  		 int argc, char * const argv[])  { -	struct hash_algo *algo;  	ulong addr, len; -	u8 output[HASH_MAX_DIGEST_SIZE]; -	u8 vsum[HASH_MAX_DIGEST_SIZE];  	if (argc < 2)  		return CMD_RET_USAGE; -	algo = find_hash_algo(algo_name); -	if (!algo) { -		printf("Unknown hash algorithm '%s'\n", algo_name); -		return CMD_RET_USAGE; -	}  	addr = simple_strtoul(*argv++, NULL, 16);  	len = simple_strtoul(*argv++, NULL, 16); -	argc -= 2; -	if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { -		puts("HASH_MAX_DIGEST_SIZE exceeded\n"); -		return 1; -	} +	if (multi_hash()) { +		struct hash_algo *algo; +		u8 output[HASH_MAX_DIGEST_SIZE]; +		u8 vsum[HASH_MAX_DIGEST_SIZE]; +		void *buf; -	algo->hash_func_ws((const unsigned char *)addr, len, output, -			   algo->chunk_size); +		algo = find_hash_algo(algo_name); +		if (!algo) { +			printf("Unknown hash algorithm '%s'\n", algo_name); +			return CMD_RET_USAGE; +		} +		argc -= 2; -	/* Try to avoid code bloat when verify is not needed */ +		if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { +			puts("HASH_MAX_DIGEST_SIZE exceeded\n"); +			return 1; +		} + +		buf = map_sysmem(addr, len); +		algo->hash_func_ws(buf, len, output, algo->chunk_size); +		unmap_sysmem(buf); + +		/* Try to avoid code bloat when verify is not needed */  #ifdef CONFIG_HASH_VERIFY -	if (verify) { +		if (flags & HASH_FLAG_VERIFY) {  #else -	if (0) { +		if (0) {  #endif -		if (!argc) -			return CMD_RET_USAGE; -		if (parse_verify_sum(algo, *argv, vsum)) { -			printf("ERROR: %s does not contain a valid %s sum\n", -				*argv, algo->name); -			return 1; -		} -		if (memcmp(output, vsum, algo->digest_size) != 0) { -			int i; +			if (!argc) +				return CMD_RET_USAGE; +			if (parse_verify_sum(algo, *argv, vsum, +					flags & HASH_FLAG_ENV)) { +				printf("ERROR: %s does not contain a valid " +					"%s sum\n", *argv, algo->name); +				return 1; +			} +			if (memcmp(output, vsum, algo->digest_size) != 0) { +				int i; +				show_hash(algo, addr, len, output); +				printf(" != "); +				for (i = 0; i < algo->digest_size; i++) +					printf("%02x", vsum[i]); +				puts(" ** ERROR **\n"); +				return 1; +			} +		} else {  			show_hash(algo, addr, len, output); -			printf(" != "); -			for (i = 0; i < algo->digest_size; i++) -				printf("%02x", vsum[i]); -			puts(" ** ERROR **\n"); -			return 1; +			printf("\n"); + +			if (argc) { +				store_result(algo, output, *argv, +					flags & HASH_FLAG_ENV); +			}  		} + +	/* Horrible code size hack for boards that just want crc32 */  	} else { -		show_hash(algo, addr, len, output); -		printf("\n"); +		ulong crc; +		ulong *ptr; + +		crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); -		if (argc) -			store_result(algo, output, *argv); +		printf("CRC32 for %08lx ... %08lx ==> %08lx\n", +				addr, addr + len - 1, crc); + +		if (argc > 3) { +			ptr = (ulong *)simple_strtoul(argv[3], NULL, 16); +			*ptr = crc; +		}  	}  	return 0; diff --git a/common/image.c b/common/image.c index ae1a9d3bd..6afbb40a9 100644 --- a/common/image.c +++ b/common/image.c @@ -74,6 +74,8 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,  #include <image.h>  #endif /* !USE_HOSTCC*/ +#include <u-boot/crc.h> +  static const table_entry_t uimage_arch[] = {  	{	IH_ARCH_INVALID,	NULL,		"Invalid ARCH",	},  	{	IH_ARCH_ALPHA,		"alpha",	"Alpha",	}, @@ -160,8 +162,6 @@ static const table_entry_t uimage_comp[] = {  	{	-1,		"",		"",			},  }; -uint32_t crc32(uint32_t, const unsigned char *, uint); -uint32_t crc32_wd(uint32_t, const unsigned char *, uint, uint);  #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)  static void genimg_print_time(time_t timestamp);  #endif diff --git a/common/lcd.c b/common/lcd.c index 66d4f94f9..590bbb930 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -33,6 +33,8 @@  #include <common.h>  #include <command.h>  #include <stdarg.h> +#include <search.h> +#include <env_callback.h>  #include <linux/types.h>  #include <stdio_dev.h>  #if defined(CONFIG_POST) @@ -1034,6 +1036,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  }  #endif +#ifdef CONFIG_SPLASH_SCREEN_PREPARE +static inline int splash_screen_prepare(void) +{ +	return board_splash_screen_prepare(); +} +#else +static inline int splash_screen_prepare(void) +{ +	return 0; +} +#endif +  static void *lcd_logo(void)  {  #ifdef CONFIG_SPLASH_SCREEN @@ -1045,6 +1059,9 @@ static void *lcd_logo(void)  		int x = 0, y = 0;  		do_splash = 0; +		if (splash_screen_prepare()) +			return (void *)gd->fb_base; +  		addr = simple_strtoul (s, NULL, 16);  #ifdef CONFIG_SPLASH_SCREEN_ALIGN  		s = getenv("splashpos"); @@ -1084,6 +1101,30 @@ static void *lcd_logo(void)  #endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */  } +#ifdef CONFIG_SPLASHIMAGE_GUARD +static int on_splashimage(const char *name, const char *value, enum env_op op, +	int flags) +{ +	ulong addr; +	int aligned; + +	if (op == env_op_delete) +		return 0; + +	addr = simple_strtoul(value, NULL, 16); +	/* See README.displaying-bmps */ +	aligned = (addr % 4 == 2); +	if (!aligned) { +		printf("Invalid splashimage value. Value must be 16 bit aligned, but not 32 bit aligned\n"); +		return -1; +	} + +	return 0; +} + +U_BOOT_ENV_CALLBACK(splashimage, on_splashimage); +#endif +  void lcd_position_cursor(unsigned col, unsigned row)  {  	console_col = min(col, CONSOLE_COLS - 1); diff --git a/common/spl/Makefile b/common/spl/Makefile index 5698a2335..da2afc11b 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -18,6 +18,7 @@ COBJS-$(CONFIG_SPL_FRAMEWORK) += spl.o  COBJS-$(CONFIG_SPL_NOR_SUPPORT) += spl_nor.o  COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += spl_ymodem.o  COBJS-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o +COBJS-$(CONFIG_SPL_ONENAND_SUPPORT) += spl_onenand.o  COBJS-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o  endif diff --git a/common/spl/spl.c b/common/spl/spl.c index 6a5a1365a..6715e0d20 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -197,6 +197,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2)  		spl_nand_load_image();  		break;  #endif +#ifdef CONFIG_SPL_ONENAND_SUPPORT +	case BOOT_DEVICE_ONENAND: +		spl_onenand_load_image(); +		break; +#endif  #ifdef CONFIG_SPL_NOR_SUPPORT  	case BOOT_DEVICE_NOR:  		spl_nor_load_image(); diff --git a/common/spl/spl_onenand.c b/common/spl/spl_onenand.c new file mode 100644 index 000000000..434930356 --- /dev/null +++ b/common/spl/spl_onenand.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 + * ISEE 2007 SL - Enric Balletbo i Serra <eballetbo@iseebcn.com> + * + * Based on common/spl/spl_nand.c + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.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 <config.h> +#include <spl.h> +#include <asm/io.h> +#include <onenand_uboot.h> + +void spl_onenand_load_image(void) +{ +	struct image_header *header; + +	debug("spl: onenand\n"); + +	/*use CONFIG_SYS_TEXT_BASE as temporary storage area */ +	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); +	/* Load u-boot */ +	onenand_spl_load_image(CONFIG_SYS_ONENAND_U_BOOT_OFFS, +		CONFIG_SYS_ONENAND_PAGE_SIZE, (void *)header); +	spl_parse_image_header(header); +	onenand_spl_load_image(CONFIG_SYS_ONENAND_U_BOOT_OFFS, +		spl_image.size, (void *)spl_image.load_addr); +} |