diff options
38 files changed, 761 insertions, 583 deletions
@@ -3811,6 +3811,15 @@ Low Level (hardware related) configuration options: that is executed before the actual U-Boot. E.g. when compiling a NAND SPL. +- CONFIG_ARCH_MAP_SYSMEM + Generally U-Boot (and in particular the md command) uses + effective address. It is therefore not necessary to regard + U-Boot address as virtual addresses that need to be translated + to physical addresses. However, sandbox requires this, since + it maintains its own little RAM buffer which contains all + addressable memory. This option causes some memory accesses + to be mapped through map_sysmem() / unmap_sysmem(). + - CONFIG_USE_ARCH_MEMCPY CONFIG_USE_ARCH_MEMSET If these options are used a optimized version of memcpy/memset will diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk index 02ce4a4..4fd0d4e 100644 --- a/arch/sandbox/config.mk +++ b/arch/sandbox/config.mk @@ -18,4 +18,5 @@ # MA 02111-1307 USA PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ -U_FORTIFY_SOURCE +PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM PLATFORM_LIBS += -lrt diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 36637af..3e37c93 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -44,6 +44,14 @@ ssize_t os_read(int fd, void *buf, size_t count) return read(fd, buf, count); } +ssize_t os_read_no_block(int fd, void *buf, size_t count) +{ + const int flags = fcntl(fd, F_GETFL, 0); + + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + return os_read(fd, buf, count); +} + ssize_t os_write(int fd, const void *buf, size_t count) { return write(fd, buf, count); diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 7603bf9..5287fd5 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -122,4 +122,7 @@ int main(int argc, char *argv[]) * never return. */ board_init_f(0); + + /* NOTREACHED - board_init_f() does not return */ + return 0; } diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index 0392d21..d8c0236 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -39,3 +39,13 @@ static inline void unmap_physmem(void *vaddr, unsigned long flags) { } + +/* For sandbox, we want addresses to point into our RAM buffer */ +static inline void *map_sysmem(phys_addr_t paddr, unsigned long len) +{ + return map_physmem(paddr, len, MAP_WRBACK); +} + +static inline void unmap_sysmem(const void *vaddr) +{ +} diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 1312a0d..b32991d 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -452,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); @@ -529,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 diff --git a/common/cmd_cbfs.c b/common/cmd_cbfs.c index 3b6cfd8..f51534b 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 e7f496e..0e43ab6 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_fdos.c b/common/cmd_fdos.c index fbee861..8ea1140 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 6eec947..ac77a08 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_hash.c b/common/cmd_hash.c index 689c608..4fe0e78 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_jffs2.c b/common/cmd_jffs2.c index 27296dd..4a4a000 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 46db962..0832e92 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; } diff --git a/common/cmd_mem.c b/common/cmd_mem.c index d44aa1d..042c994 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,11 +481,12 @@ 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; @@ -477,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++; @@ -506,28 +538,30 @@ 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; @@ -550,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; @@ -579,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; @@ -594,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 */ @@ -634,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; - } - - 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++; + num_words = (end_addr - start_addr) / sizeof(vu_long); - /* - * 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 = 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 + + * 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. + */ + pattern = (vu_long) 0xaaaaaaaa; + anti_pattern = (vu_long) 0x55555555; - 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; - } + 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; - start[test_offset] = anti_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 */ } @@ -962,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; @@ -1006,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] == '-')) { @@ -1042,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; @@ -1060,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_mtdparts.c b/common/cmd_mtdparts.c index 06fc171..0cfca0c 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 495610c..32348f3 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, diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 7633f0c..d646d90 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); } @@ -891,8 +891,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_reiser.c b/common/cmd_reiser.c index e658618..717c7f6 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_setexpr.c b/common/cmd_setexpr.c index 5a04295..7a38e94 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 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/cmd_unzip.c b/common/cmd_unzip.c index 43ed791..7470c2b 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 42a7eba..ea0a26e 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 1df0c4d..900e977 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 a73c86d..8607da8 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/hash.c b/common/hash.c index e3a6e43..f5badcb 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 ae1a9d3..6afbb40 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/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 49c74c2..8d70586 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -362,7 +362,6 @@ static void fm_init_qmi(struct fm_qmi_common *qmi) int fm_init_common(int index, struct ccsr_fman *reg) { int rc; - char env_addr[32]; #if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) void *addr = (void *)CONFIG_SYS_QE_FMAN_FW_ADDR; #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND) @@ -416,8 +415,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) rc = fman_upload_firmware(index, ®->fm_imem, addr); if (rc) return rc; - sprintf(env_addr, "0x%lx", (long unsigned int)addr); - setenv("fman_ucode", env_addr); + setenv_addr("fman_ucode", addr); fm_init_muram(index, ®->muram); fm_init_qmi(®->fm_qmi_common); diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index cb19401..b73520c 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -30,6 +30,19 @@ #include <serial.h> #include <linux/compiler.h> +/* + * + * serial_buf: A buffer that holds keyboard characters for the + * Sandbox U-boot. + * + * invariants: + * serial_buf_write == serial_buf_read -> empty buffer + * (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer + */ +static char serial_buf[16]; +static unsigned int serial_buf_write; +static unsigned int serial_buf_read; + static int sandbox_serial_init(void) { os_tty_raw(0); @@ -50,18 +63,37 @@ static void sandbox_serial_puts(const char *str) os_write(1, str, strlen(str)); } -static int sandbox_serial_getc(void) +static unsigned int increment_buffer_index(unsigned int index) +{ + return (index + 1) % ARRAY_SIZE(serial_buf); +} + +static int sandbox_serial_tstc(void) { - char buf; + const unsigned int next_index = + increment_buffer_index(serial_buf_write); ssize_t count; - count = os_read(0, &buf, 1); - return count == 1 ? buf : 0; + os_usleep(100); + if (next_index == serial_buf_read) + return 1; /* buffer full */ + + count = os_read_no_block(0, &serial_buf[serial_buf_write], 1); + if (count == 1) + serial_buf_write = next_index; + return serial_buf_write != serial_buf_read; } -static int sandbox_serial_tstc(void) +static int sandbox_serial_getc(void) { - return 0; + int result; + + while (!sandbox_serial_tstc()) + ; /* buffer empty */ + + result = serial_buf[serial_buf_read]; + serial_buf_read = increment_buffer_index(serial_buf_read); + return result; } static struct serial_device sandbox_serial_drv = { @@ -256,7 +256,6 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], unsigned long bytes; unsigned long pos; int len_read; - char buf[12]; unsigned long time; if (argc < 2) @@ -308,8 +307,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], } puts("\n"); - sprintf(buf, "0x%x", len_read); - setenv("filesize", buf); + setenv_hex("filesize", len_read); return 0; } diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 44be3f5..273c0a9 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -687,7 +687,6 @@ int ubifs_load(char *filename, u32 addr, u32 size) int i; int count; int last_block_size = 0; - char buf [10]; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get @@ -740,8 +739,7 @@ int ubifs_load(char *filename, u32 addr, u32 size) if (err) printf("Error reading file '%s'\n", filename); else { - sprintf(buf, "%X", size); - setenv("filesize", buf); + setenv_hex("filesize", size); printf("Done\n"); } diff --git a/include/common.h b/include/common.h index 4ad17ea..6d52924 100644 --- a/include/common.h +++ b/include/common.h @@ -270,7 +270,8 @@ int cpu_init(void); phys_size_t initdram (int); int display_options (void); void print_size(unsigned long long, const char *); -int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen); +int print_buffer(ulong addr, const void *data, uint width, uint count, + uint linelen); /* common/main.c */ void main_loop (void); @@ -357,7 +358,19 @@ int getenv_yesno(const char *var); int saveenv (void); int setenv (const char *, const char *); int setenv_ulong(const char *varname, ulong value); -int setenv_addr(const char *varname, const void *addr); +int setenv_hex(const char *varname, ulong value); +/** + * setenv_addr - Set an environment variable to an address in hex + * + * @varname: Environmet variable to set + * @addr: Value to set it to + * @return 0 if ok, 1 on error + */ +static inline int setenv_addr(const char *varname, const void *addr) +{ + return setenv_hex(varname, (ulong)addr); +} + #ifdef CONFIG_ARM # include <asm/mach-types.h> # include <asm/setup.h> @@ -869,6 +882,18 @@ int cpu_disable(int nr); int cpu_release(int nr, int argc, char * const argv[]); #endif +/* Define a null map_sysmem() if the architecture doesn't use it */ +# ifndef CONFIG_ARCH_MAP_SYSMEM +static inline void *map_sysmem(phys_addr_t paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline void unmap_sysmem(const void *vaddr) +{ +} +# endif + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PPC diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 9c431bf..9f51a0b 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -63,8 +63,8 @@ #define CONFIG_SYS_HZ 1000 /* Memory things - we don't really want a memory test */ -#define CONFIG_SYS_LOAD_ADDR 0x10000000 -#define CONFIG_SYS_MEMTEST_START 0x10000000 +#define CONFIG_SYS_LOAD_ADDR 0x00000000 +#define CONFIG_SYS_MEMTEST_START 0x00100000 #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + 0x1000) #define CONFIG_PHYS_64BIT @@ -85,6 +85,11 @@ #undef CONFIG_CMD_NET #undef CONFIG_CMD_NFS +#define CONFIG_CMD_HASH +#define CONFIG_HASH_VERIFY +#define CONFIG_SHA1 +#define CONFIG_SHA256 + #define CONFIG_BOOTARGS "" #define CONFIG_EXTRA_ENV_SETTINGS "stdin=serial\0" \ diff --git a/include/hash.h b/include/hash.h index 34ba558..2dbbd9b 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 @@ -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 + * @algo_name: Hash algorithm being used (lower case!) + * @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 diff --git a/include/os.h b/include/os.h index 699682a..c452d1b 100644 --- a/include/os.h +++ b/include/os.h @@ -40,6 +40,16 @@ struct sandbox_state; ssize_t os_read(int fd, void *buf, size_t count); /** + * Access to the OS read() system call with non-blocking access + * + * \param fd File descriptor as returned by os_open() + * \param buf Buffer to place data + * \param count Number of bytes to read + * \return number of bytes read, or -1 on error + */ +ssize_t os_read_no_block(int fd, void *buf, size_t count); + +/** * Access to the OS write() system call * * \param fd File descriptor as returned by os_open() 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)); +} diff --git a/lib/display_options.c b/lib/display_options.c index 694d2f2..0339970 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -98,7 +98,8 @@ void print_size(unsigned long long size, const char *s) */ #define MAX_LINE_LENGTH_BYTES (64) #define DEFAULT_LINE_LENGTH_BYTES (16) -int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen) +int print_buffer(ulong addr, const void *data, uint width, uint count, + uint linelen) { /* linebuf as a union causes proper alignment */ union linebuf { @@ -528,15 +528,11 @@ restart: case NETLOOP_SUCCESS: net_cleanup_loop(); if (NetBootFileXferSize > 0) { - char buf[20]; printf("Bytes transferred = %ld (%lx hex)\n", NetBootFileXferSize, NetBootFileXferSize); - sprintf(buf, "%lX", NetBootFileXferSize); - setenv("filesize", buf); - - sprintf(buf, "%lX", (unsigned long)load_addr); - setenv("fileaddr", buf); + setenv_hex("filesize", NetBootFileXferSize); + setenv_hex("fileaddr", load_addr); } if (protocol != NETCONS) eth_halt(); |