diff options
| author | Tom Rini <trini@ti.com> | 2013-03-11 12:02:40 -0400 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2013-03-11 12:16:13 -0400 | 
| commit | 76b40ab41eff1f402ee52ba768b09daad293b9bb (patch) | |
| tree | 4956296adbdc8939aa49d84fa9bd497eef65b7f4 /common/hash.c | |
| parent | de62688bb61c499ecc2d70a3aa8ccf90bb7a8ef6 (diff) | |
| parent | fc959081d41aab2d6f4614c5fb3dd1b77ffcdcf4 (diff) | |
| download | olio-uboot-2014.01-76b40ab41eff1f402ee52ba768b09daad293b9bb.tar.xz olio-uboot-2014.01-76b40ab41eff1f402ee52ba768b09daad293b9bb.zip | |
Merge u-boot/master into u-boot-ti/master
In master we had already taken a patch to fix the davinci GPIO code for
CONFIG_SOC_DM646X and in u-boot-ti we have additional patches to support
DA830 (which is CONFIG_SOC_DA8XX && !CONFIG_SOC_DA850).  Resolve these
conflicts manually and comment the #else/#endif lines for clarity.
Conflicts:
	arch/arm/include/asm/arch-davinci/gpio.h
	drivers/gpio/da8xx_gpio.c
Signed-off-by: Tom Rini <trini@ti.com>
Diffstat (limited to 'common/hash.c')
| -rw-r--r-- | common/hash.c | 194 | 
1 files changed, 140 insertions, 54 deletions
| 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; |