summaryrefslogtreecommitdiff
path: root/common/hash.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2013-02-24 20:30:22 +0000
committerSimon Glass <sjg@chromium.org>2013-02-28 19:09:23 -0800
commitd20a40de9db07de1f1f06a79a4da1cdda5379b75 (patch)
tree6d1952a17439f0ffa0fb09882f7a3df2a0e917e1 /common/hash.c
parentd5b76673a5dfe0b5250baea3c36cdfa7a9fd5230 (diff)
downloadu-boot-d20a40de9db07de1f1f06a79a4da1cdda5379b75.tar.gz
u-boot-d20a40de9db07de1f1f06a79a4da1cdda5379b75.tar.bz2
u-boot-d20a40de9db07de1f1f06a79a4da1cdda5379b75.zip
Roll crc32 into hash infrastructure
Add the CRC32 algorithm to the list of available hashes, and make the crc32 command use hash_command(). Add a new crc32_wd_buf() to make this possible, which puts its result in a buffer rather than returning it as a 32-bit value. Note: For some boards the hash command is not enabled, neither are sha1, sha256 or the verify option. In this case the full hash implementation adds about 500 bytes of overhead. So as a special case, we use #ifdef to select very simple bahaviour in that case. The justification for this is that it is currently a very common case (virtually all boards enable crc32 but only some enable more advanced features). Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/hash.c')
-rw-r--r--common/hash.c118
1 files changed, 80 insertions, 38 deletions
diff --git a/common/hash.c b/common/hash.c
index 462853d172..ef6fe375d2 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -34,13 +34,19 @@
* crypto could perhaps add named version of these algorithms here.
*/
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_SUM_LEN,
sha1_csum_wd,
CHUNKSZ_SHA1,
},
+#define MULTI_HASH
#endif
#ifdef CONFIG_SHA256
{
@@ -49,9 +55,27 @@ static struct hash_algo hash_algo[] = {
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
*
@@ -192,10 +216,7 @@ static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
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;
@@ -203,52 +224,73 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
addr = simple_strtoul(*argv++, NULL, 16);
len = simple_strtoul(*argv++, NULL, 16);
- algo = find_hash_algo(algo_name);
- if (!algo) {
- printf("Unknown hash algorithm '%s'\n", algo_name);
- return CMD_RET_USAGE;
- }
- argc -= 2;
+ if (multi_hash()) {
+ struct hash_algo *algo;
+ u8 output[HASH_MAX_DIGEST_SIZE];
+ u8 vsum[HASH_MAX_DIGEST_SIZE];
- if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
- puts("HASH_MAX_DIGEST_SIZE exceeded\n");
- return 1;
- }
+ algo = find_hash_algo(algo_name);
+ if (!algo) {
+ printf("Unknown hash algorithm '%s'\n", algo_name);
+ return CMD_RET_USAGE;
+ }
+ argc -= 2;
+
+ if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
+ puts("HASH_MAX_DIGEST_SIZE exceeded\n");
+ return 1;
+ }
- algo->hash_func_ws((const unsigned char *)addr, len, output,
- algo->chunk_size);
+ algo->hash_func_ws((const unsigned char *)addr, len, output,
+ algo->chunk_size);
- /* Try to avoid code bloat when verify is not needed */
+ /* Try to avoid code bloat when verify is not needed */
#ifdef CONFIG_HASH_VERIFY
- if (flags & HASH_FLAG_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,
+ 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;
+ 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);
+
+ printf("CRC32 for %08lx ... %08lx ==> %08lx\n",
+ addr, addr + len - 1, crc);
- if (argc) {
- store_result(algo, output, *argv,
- flags & HASH_FLAG_ENV);
+ if (argc > 3) {
+ ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
+ *ptr = crc;
}
}