[U-Boot] [PATCH v2 16/21] hash: Add a flag to support saving hashes in the environment

Some hashing commands permit saving the hash in an environment variable, and verifying a hash from there. But the crc32 command does not support this. In order to permit crc32 to use the generic hashing infrastructure, add a flag to select which behaviour to use.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v2: - Add new patch to control saving hashes in the environment
common/cmd_hash.c | 8 +++--- common/cmd_sha1sum.c | 6 ++--- common/hash.c | 69 +++++++++++++++++++++++++++++++++++++++------------- include/hash.h | 9 +++++-- 4 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/common/cmd_hash.c b/common/cmd_hash.c index eb6a338..8c03b5c 100644 --- a/common/cmd_hash.c +++ b/common/cmd_hash.c @@ -30,22 +30,22 @@ static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { #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 verify = 0; + 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); + return hash_command(*argv, flags, cmdtp, flag, argc - 1, argv + 1); }
#ifdef CONFIG_HASH_VERIFY diff --git a/common/cmd_sha1sum.c b/common/cmd_sha1sum.c index fe927ab..9f08629 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/hash.c b/common/hash.c index e3a6e43..021c4d9 100644 --- a/common/hash.c +++ b/common/hash.c @@ -58,19 +58,31 @@ static struct hash_algo hash_algo[] = { * @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 ia 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 +92,11 @@ static void store_result(struct hash_algo *algo, const u8 *sum, } str_ptr = '\0'; setenv(dest, str_output); + } else { + u8 *ptr; + + ptr = (u8 *)simple_strtoul(dest, NULL, 16); + memcpy(ptr, sum, algo->digest_size); } }
@@ -94,14 +111,28 @@ 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 == '*') { + int env_var = 0; + + /* See comment above in store_result() */ + if (allow_env_vars) { + if (*verify_str == '*') + verify_str++; + else + env_var = 1; + } + + if (env_var) { u8 *ptr;
- ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16); + ptr = (u8 *)simple_strtoul(verify_str, NULL, 16); memcpy(vsum, ptr, algo->digest_size); } else { unsigned int i; @@ -158,7 +189,7 @@ 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; @@ -169,13 +200,14 @@ int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, if (argc < 2) return CMD_RET_USAGE;
+ 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; } - addr = simple_strtoul(*argv++, NULL, 16); - len = simple_strtoul(*argv++, NULL, 16); argc -= 2;
if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { @@ -188,13 +220,14 @@ int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
/* Try to avoid code bloat when verify is not needed */ #ifdef CONFIG_HASH_VERIFY - if (verify) { + if (flags & HASH_FLAG_VERIFY) { #else if (0) { #endif if (!argc) return CMD_RET_USAGE; - if (parse_verify_sum(algo, *argv, vsum)) { + 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; @@ -213,8 +246,10 @@ int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, show_hash(algo, addr, len, output); printf("\n");
- if (argc) - store_result(algo, output, *argv); + if (argc) { + store_result(algo, output, *argv, + flags & HASH_FLAG_ENV); + } }
return 0; diff --git a/include/hash.h b/include/hash.h index 34ba558..88fa2b5 100644 --- a/include/hash.h +++ b/include/hash.h @@ -51,19 +51,24 @@ struct hash_algo { */ #define HASH_MAX_DIGEST_SIZE 32
+enum { + HASH_FLAG_VERIFY = 1 << 0, /* Enable verify mode */ + HASH_FLAG_ENV = 1 << 1, /* Allow env vars */ +}; + /** * hash_command: Process a hash command for a particular algorithm * * This common function is used to implement specific hash commands. * * @algo_name: Hash algorithm being used - * @verify: Non-zero to enable verify mode + * @flags: Flags value (HASH_FLAG_...) * @cmdtp: Pointer to command table entry * @flag: Some flags normally 0 (see CMD_FLAG_.. above) * @argc: Number of arguments (arg 0 must be the command text) * @argv: Arguments */ -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[]);
#endif

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 bahviour 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 --- Changes in v2: - Rewrite crc32 support in hash to improve code size
common/cmd_mem.c | 75 ++++------------------------------ common/hash.c | 111 ++++++++++++++++++++++++++++++++++----------------- include/hash.h | 2 +- include/u-boot/crc.h | 11 +++++ lib/crc32.c | 9 +++++ 5 files changed, 102 insertions(+), 106 deletions(-)
diff --git a/common/cmd_mem.c b/common/cmd_mem.c index f67cd15..150a428 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -32,6 +32,7 @@ #ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #endif +#include <hash.h> #include <watchdog.h> #include <asm/io.h> #include <linux/compiler.h> @@ -1096,89 +1097,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 021c4d9..984cbe4 100644 --- a/common/hash.c +++ b/common/hash.c @@ -41,6 +41,7 @@ static struct hash_algo hash_algo[] = { sha1_csum_wd, CHUNKSZ_SHA1, }, +#define MULTI_HASH #endif #ifdef CONFIG_SHA256 { @@ -49,9 +50,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 +211,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 +219,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)); +}

Dear Simon Glass,
In message 1361379515-23802-18-git-send-email-sjg@chromium.org you wrote:
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 bahviour in
s/bahviour/behaviour/
Best regards,
Wolfgang Denk

Use map_sysmem() so that hashing is possible on sandbox.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v2: - Rebase on top of earlier patches
common/hash.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 984cbe4..1c33ef7 100644 --- a/common/hash.c +++ b/common/hash.c @@ -28,6 +28,7 @@ #include <hash.h> #include <sha1.h> #include <sha256.h> +#include <asm/io.h>
/* * These are the hash algorithms we support. Chips which support accelerated @@ -112,10 +113,13 @@ static void store_result(struct hash_algo *algo, const u8 *sum, str_ptr = '\0'; setenv(dest, str_output); } else { - u8 *ptr; + ulong addr; + void *buf;
- ptr = (u8 *)simple_strtoul(dest, NULL, 16); - memcpy(ptr, sum, algo->digest_size); + addr = simple_strtoul(dest, NULL, 16); + buf = map_sysmem(addr, algo->digest_size); + memcpy(buf, sum, algo->digest_size); + unmap_sysmem(buf); } }
@@ -149,10 +153,12 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum, }
if (env_var) { - u8 *ptr; + ulong addr; + void *buf;
- ptr = (u8 *)simple_strtoul(verify_str, NULL, 16); - memcpy(vsum, ptr, algo->digest_size); + 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; @@ -223,6 +229,7 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, struct hash_algo *algo; u8 output[HASH_MAX_DIGEST_SIZE]; u8 vsum[HASH_MAX_DIGEST_SIZE]; + void *buf;
algo = find_hash_algo(algo_name); if (!algo) { @@ -236,8 +243,9 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, return 1; }
- algo->hash_func_ws((const unsigned char *)addr, len, output, - algo->chunk_size); + 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

Dear Simon Glass,
In message 1361379515-23802-17-git-send-email-sjg@chromium.org you wrote:
Some hashing commands permit saving the hash in an environment variable, and verifying a hash from there. But the crc32 command does not support this. In order to permit crc32 to use the generic hashing infrastructure, add a flag to select which behaviour to use.
<nitpick>
...
- /*
* 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 ia always an
s/it ia/it is/
</nitpick>
What's the impact of these changes on the memory footprint?
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Thu, Feb 21, 2013 at 4:04 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1361379515-23802-17-git-send-email-sjg@chromium.org you wrote:
Some hashing commands permit saving the hash in an environment variable, and verifying a hash from there. But the crc32 command does not support this. In order to permit crc32 to use the generic hashing infrastructure, add a flag to select which behaviour to use.
<nitpick>
...
/*
* 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 ia always an
s/it ia/it is/
</nitpick>
What's the impact of these changes on the memory footprint?
Overall it is pretty neutral, although there are some variations. For powerpc the overall affect is to save an average of 13.9 bytes across the whole image. arm does a bit better:
24: hash: Use lower case for hash algorithm names sandbox: sandbox x86: (for 1/1 boards) all -74.0 data +16.0 rodata +10.0 text -100.0 m68k: (for 41/50 boards) all -44.7 bss +0.5 data +0.8 rodata -1.0 text -44.9 powerpc: (for 633/635 boards) all -13.9 bss +14.4 data -3.6 rodata -19.6 text -5.1 sandbox: (for 1/1 boards) all +24336.0 bss +48.0 data +168.0 rodata +432.0 text +23688.0 sh: (for 16/21 boards) all +18.8 rodata -1.2 text +20.0 nios2: (for 3/3 boards) all +277.3 text +277.3 microblaze: (for 1/1 boards) all -832.0 bss +8.0 data -16.0 rodata -120.0 text -704.0 arm: (for 292/292 boards) all -277.8 bss +0.4 data +0.3 rodata -3.8 spl/u-boot-spl:all -0.2 spl/u-boot-spl:rodata -0.1 spl/u-boot-spl:text -0.1 text -274.7 nds32: (for 3/3 boards) all -116.0 data +4.0 rodata -16.0 text -104.0
Bad boards define CONFIG_CMD_CRC32 along with CONFIG_CRC32_VERIFY, thus bringing in the hash code, but they don't enable the hash command or have sha1, so this is the worst case. Good boards benefit from the getenv/setenv helpers and use the small version of the hash code (since they only define CONFIG_CMD_CRC32). The vast majority of boards show a slight improvement overall.
This is the worst powerpc board:
powerpc: (for 2/2 boards) all +284.5 bss +12.0 rodata -13.5 text +286.0 stxxtc : all +941 bss +24 data +16 rodata +89 text +812 u-boot: add: 8/0, grow: 3/-10 bytes: 1254/-432 (822) function old new delta hash_command - 740 +740 show_hash - 108 +108 simple_itoa - 104 +104 crc32_wd_buf - 76 +76 setenv_hex - 64 +64 setenv_ulong - 52 +52 do_mem_mtest 468 512 +44 static.local - 22 +22 do_mem_loop 268 288 +20 hash_algo - 16 +16 do_mem_cmp 356 364 +8 do_mem_mw 224 220 -4 set_working_fdt_addr 68 52 -16 load_serial_ymodem 288 272 -16 load_serial 504 488 -16 do_load_serial_bin 1812 1796 -16 do_imgextract 656 620 -36 NetLoop 784 748 -36 do_bootm 1216 1164 -52 do_mem_cp 344 288 -56 do_mem_crc 308 124 -184
This is the best powerpc board:
P2041RDB_SRIO_PCIE_BOOT: all -372 data -16 rodata -116 text -240 u-boot: add: 5/-1, grow: 2/-15 bytes: 446/-640 (-194) function old new delta hash_command - 176 +176 simple_itoa - 104 +104 setenv_hex - 64 +64 setenv_ulong - 52 +52 static.local - 22 +22 do_mem_loop 268 288 +20 do_mem_cmp 324 332 +8 do_mem_mw 224 220 -4 set_working_fdt_addr 68 52 -16 load_serial_ymodem 228 212 -16 load_serial 460 444 -16 hash_algo 16 - -16 fm_init_common 1336 1320 -16 do_load_serial_bin 1812 1796 -16 do_load 460 444 -16 do_imgextract 864 828 -36 NetLoop 780 744 -36 nand_print_and_set_info 224 172 -52 do_bootm 1236 1184 -52 do_setexpr 436 376 -60 do_mem_cp 244 156 -88 do_mem_crc 184 88 -96 do_mem_mtest 1400 1296 -104
This is tricky because I am trying to bring in a generic infrastructure for hashing and make use of it everywhere, but unfortunately those boards that don't really make much use of it still have to pay a price. That said, only 15 powerpc boards are in the 'bad' camp and none is as bad as stxxtc.
There is also some saving to be had by changing simple_itoa() to use the existing put_dec() if we want to. Overall I'm hoping that the crc32 patch is worth the trouble.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de Let us not look back in anger or forward in fear, but around in awareness. - James Thurber
participants (2)
-
Simon Glass
-
Wolfgang Denk