From patchwork Mon Feb 25 06:30:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 222852 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 6DFC82C02AB for ; Mon, 25 Feb 2013 17:30:58 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DF1B74A47B; Mon, 25 Feb 2013 07:30:56 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id cVhYHdCcIvBD; Mon, 25 Feb 2013 07:30:56 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 042284A47C; Mon, 25 Feb 2013 07:30:54 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 73D154A47C for ; Mon, 25 Feb 2013 07:30:51 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XDysw3VI2E45 for ; Mon, 25 Feb 2013 07:30:50 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-gh0-f201.google.com (mail-gh0-f201.google.com [209.85.160.201]) by theia.denx.de (Postfix) with ESMTPS id 18E834A47B for ; Mon, 25 Feb 2013 07:30:48 +0100 (CET) Received: by mail-gh0-f201.google.com with SMTP id z19so261458ghb.4 for ; Sun, 24 Feb 2013 22:30:47 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=JG0IP+IPM5oG5nsNocWc+gSU4N5sEZQK5tKA0yqv5wo=; b=KhWU/43xyo0sFoLinG22jkhYEHsRWscRVt2qqiPnc5mfjYqHcoFaW+XmlRyKRZp1p4 JXb/bYZgPRKZqm6OVbP5NAGCUlZAsglMFT2VBKFt2cAVopSpsYhlvbAJ7XezaOk44OJG N5bdltqlEcua4YZpOwFU3r7hEkkGWvTbrkXCHZr3UKPvJUQ9e6XNJgpQoaNzqsjSuSoT mZJqb9n/Ffa2ikKsz78hygRWrHC514rfBUZe7EIpGfFES28Ht6lUjBETdOIvxkwwAKS0 h0NSgLkvlyG52LwO4nFO5Ojal3P1DXkNXeLesfCOCD+K0893CbhCnViu9jDMLAWSfK2d s2Kg== X-Received: by 10.236.118.137 with SMTP id l9mr6284327yhh.5.1361773847468; Sun, 24 Feb 2013 22:30:47 -0800 (PST) Received: from corp2gmr1-1.hot.corp.google.com (corp2gmr1-1.hot.corp.google.com [172.24.189.92]) by gmr-mx.google.com with ESMTPS id u21si827601yhj.0.2013.02.24.22.30.47 (version=TLSv1.1 cipher=AES128-SHA bits=128/128); Sun, 24 Feb 2013 22:30:47 -0800 (PST) Received: from kaka.mtv.corp.google.com (kaka.mtv.corp.google.com [172.22.73.79]) by corp2gmr1-1.hot.corp.google.com (Postfix) with ESMTP id 4342A31C2C4; Sun, 24 Feb 2013 22:30:47 -0800 (PST) Received: by kaka.mtv.corp.google.com (Postfix, from userid 121222) id 00F4316074D; Sun, 24 Feb 2013 22:30:41 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Date: Sun, 24 Feb 2013 22:30:22 -0800 Message-Id: <1361773827-12993-18-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 1.8.1.3 X-Gm-Message-State: ALoCoQmLA/GCPXP6TsZtam38Jx9cR39kowSl3cmmgvGXj6t0K5VpgKagscW9K4mSzohy9k+7v+omWQbfXcyn9N6KQkGmNNpuxLsCJDxQZpFohJbWVT79S9kqvOU9G158EigDQZQ6nqy/rtSFtxeGqoz15aYy0M561aFcqiFO3QWYK4V87Kb6eYYLQFRwb3qVOEidLVChGmzS Cc: Tom Rini Subject: [U-Boot] [PATCH v4 17/22] Roll crc32 into hash infrastructure X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 --- Changes in v4: - Use CONFIG_CMD_SHA1SUM instead of the non-existent CONFIG_CMD_SHA1 Changes in v3: - Fix 'bahviour' typo - Make sha1 code dependent on CONFIG_CMD_SHA1, for code size reasons Changes in v2: - Rewrite crc32 support in hash to improve code size common/cmd_mem.c | 75 +++----------------------------- common/hash.c | 118 ++++++++++++++++++++++++++++++++++----------------- include/hash.h | 2 +- include/u-boot/crc.h | 11 +++++ lib/crc32.c | 9 ++++ 5 files changed, 108 insertions(+), 107 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 12dbc16..95b49b2 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -32,6 +32,7 @@ #ifdef CONFIG_HAS_DATAFLASH #include #endif +#include #include #include #include @@ -1098,89 +1099,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/hash.c b/common/hash.c index 462853d..ef6fe37 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; } } diff --git a/include/hash.h b/include/hash.h index 88fa2b5..f2b2c45 100644 --- a/include/hash.h +++ b/include/hash.h @@ -22,7 +22,7 @@ #ifndef _HASH_H #define _HASH_H -#ifdef CONFIG_SHA1SUM_VERIFY +#if defined(CONFIG_SHA1SUM_VERIFY) || defined(CONFIG_CRC32_VERIFY) #define CONFIG_HASH_VERIFY #endif diff --git a/include/u-boot/crc.h b/include/u-boot/crc.h index 07badbf..08e509e 100644 --- a/include/u-boot/crc.h +++ b/include/u-boot/crc.h @@ -30,4 +30,15 @@ uint32_t crc32 (uint32_t, const unsigned char *, uint); uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint); uint32_t crc32_no_comp (uint32_t, const unsigned char *, uint); +/** + * crc32_wd_buf - Perform CRC32 on a buffer and return result in buffer + * + * @input: Input buffer + * @ilen: Input buffer length + * @output: Place to put checksum result (4 bytes) + * @chunk_sz: Trigger watchdog after processing this many bytes + */ +void crc32_wd_buf(const unsigned char *input, uint ilen, + unsigned char *output, uint chunk_sz); + #endif /* _UBOOT_CRC_H */ diff --git a/lib/crc32.c b/lib/crc32.c index 27335a3..76205da 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -249,3 +249,12 @@ uint32_t ZEXPORT crc32_wd (uint32_t crc, return crc; } + +void crc32_wd_buf(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + uint32_t crc; + + crc = crc32_wd(0, input, ilen, chunk_sz); + memcpy(output, &crc, sizeof(crc)); +}