Merge branch 'mem' of git://git.denx.de/u-boot-x86
diff --git a/README b/README
index 0070694..51eb71b 100644
--- a/README
+++ b/README
@@ -3811,6 +3811,15 @@
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 @@
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 @@
* 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 @@
{
}
+
+/* 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 @@
/* 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 @@
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 @@
const struct cbfs_cachenode *file;
unsigned long offset;
unsigned long count;
- char buf[12];
long size;
if (argc < 3) {
@@ -95,8 +94,7 @@
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 @@
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 @@
char *name;
char *ep;
int size;
- char buf [12];
int drive = CONFIG_SYS_FDC_DRIVE_NUMBER;
/* pre-set load_addr */
@@ -91,8 +90,7 @@
}
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 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 @@
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 ulong load_serial_ymodem(ulong offset)
{
int size;
- char buf[32];
int err;
int res;
connection_info_t info;
@@ -1012,8 +1007,7 @@
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 @@
# 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 @@
{
ulong addr, writeval, count;
int size;
+ void *buf;
+ ulong bytes;
if ((argc < 3) || (argc > 4))
return CMD_RET_USAGE;
@@ -188,15 +200,18 @@
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 @@
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 @@
}
#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_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 @@
}
#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_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 @@
*/
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 @@
}
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 @@
/* 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 @@
}
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 @@
}
#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,20 +654,292 @@
0x00000055, /* four non-adjacent bits */
0xaaaaaaaa, /* alternating 1/0 */
};
+
+ 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 = 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())
+ 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())
+ 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.
+ */
+
+ /*
+ * 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", __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;
+ addr[test_offset] = anti_pattern;
+
+ 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",
+ start_addr + offset, pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ addr[test_offset] = pattern;
+ WATCHDOG_RESET();
+
+ /*
+ * 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 < 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",
+ start_addr + offset, pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ 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++;
+
+ /*
+ * 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 = addr[offset];
+ if (temp != pattern) {
+ printf("\nFAILURE (read/write) @ 0x%.8lx:"
+ " expected 0x%.8lx, actual 0x%.8lx)\n",
+ start_addr + offset, pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+
+ 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",
+ start_addr + offset, anti_pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ addr[offset] = 0;
+ }
+
+ return 0;
+}
+
+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)
+ pattern = -pattern; /* complement & increment */
+ 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;
+ }
+ 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
- ulong incr;
- ulong pattern;
+ const int alt_test = 0;
#endif
if (argc > 1)
- start = (ulong *)simple_strtoul(argv[1], NULL, 16);
+ start = simple_strtoul(argv[1], NULL, 16);
else
- start = (ulong *)CONFIG_SYS_MEMTEST_START;
+ start = CONFIG_SYS_MEMTEST_START;
if (argc > 2)
- end = (ulong *)simple_strtoul(argv[2], NULL, 16);
+ end = simple_strtoul(argv[2], NULL, 16);
else
- end = (ulong *)(CONFIG_SYS_MEMTEST_END);
+ end = CONFIG_SYS_MEMTEST_END;
if (argc > 3)
pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
@@ -659,295 +951,56 @@
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);
+ printf("Testing %08x ... %08x:\n", (uint)start, (uint)end);
+ debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__,
+ start, end);
- for (;;) {
+ 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()) {
- putc ('\n');
- return 1;
+ errs = -1UL;
+ break;
}
-
- 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);
+ printf("Iteration: %6d\r", iteration + 1);
debug("\n");
- iterations++;
-
- /*
- * 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 */
- readback = *addr;
- if(readback != val) {
- printf ("FAILURE (data line): "
- "expected %08lx, actual %08lx\n",
- val, readback);
- errs++;
- if (ctrlc()) {
- putc ('\n');
- 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 (alt_test) {
+ errs = mem_test_alt(buf, start, end, dummy);
+ } else {
+ errs = mem_test_quick(buf, start, end, pattern,
+ iteration);
}
-
- /*
- * 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;
-
- 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;
- }
-
- /*
- * Check for address bits stuck high.
- */
- test_offset = 0;
- start[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:"
- " expected 0x%.8lx, actual 0x%.8lx\n",
- (ulong)&start[offset], pattern, temp);
- errs++;
- if (ctrlc()) {
- putc ('\n');
- return 1;
- }
- }
- }
- start[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;
-
- for (offset = 1; offset < len; offset <<= 1) {
- temp = start[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;
- }
- }
- }
- start[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;
-
- /*
- * Fill memory with a known pattern.
- */
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- WATCHDOG_RESET();
- start[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:"
- " expected 0x%.8lx, actual 0x%.8lx)\n",
- (ulong)&start[offset], pattern, temp);
- errs++;
- if (ctrlc()) {
- putc ('\n');
- return 1;
- }
- }
-
- anti_pattern = ~pattern;
- start[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 = start[offset];
- if (temp != anti_pattern) {
- printf ("\nFAILURE (read/write): @ 0x%.8lx:"
- " expected 0x%.8lx, actual 0x%.8lx)\n",
- (ulong)&start[offset], anti_pattern, temp);
- errs++;
- if (ctrlc()) {
- putc ('\n');
- return 1;
- }
- }
- start[offset] = 0;
- }
+ if (errs == -1UL)
+ break;
}
-#else /* The original, quickie test */
- incr = 1;
- for (;;) {
- if (ctrlc()) {
- putc ('\n');
- return 1;
- }
+ /*
+ * 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;
- 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...");
-
- 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;
- }
-
- /*
- * 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) {
- pattern = -pattern; /* complement & increment */
- }
- else {
- pattern = ~pattern;
- }
- incr = -incr;
+ unmap_sysmem(vbuf);
+ unmap_sysmem(vdummy);
}
-#endif
- return 0; /* not reached */
+
+ 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 @@
{
ulong addr, i;
int nbytes, size;
+ void *ptr = NULL;
if (argc != 2)
return CMD_RET_USAGE;
@@ -1006,13 +1060,14 @@
* 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 @@
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 @@
#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;
+ int flags = 0;
+ int ac;
+ char * const *av;
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 ac;
- char * const *av;
-
- if (argc < 3) {
-usage:
- 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 index_partitions(void)
{
- char buf[16];
u16 mtddevnum;
struct part_info *part;
struct list_head *dentry;
@@ -244,8 +243,7 @@
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 @@
{
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 @@
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 @@
}
/**
- * 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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
{
unsigned long src, dst;
unsigned long src_len = ~0UL, dst_len = ~0UL;
- char buf[32];
switch (argc) {
case 4:
@@ -46,8 +45,7 @@
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 @@
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 @@
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 @@
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 @@
{
unsigned long src, dst;
unsigned long src_len, dst_len = ~0UL;
- char buf[32];
switch (argc) {
case 5:
@@ -47,8 +46,7 @@
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 @@
}
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 @@
* 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;
- ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
- memcpy(vsum, ptr, algo->digest_size);
+ /* See comment above in store_result() */
+ if (allow_env_vars) {
+ if (*verify_str == '*')
+ verify_str++;
+ else
+ env_var = 1;
+ }
+
+ 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 @@
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 @@
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);
-
- /* Try to avoid code bloat when verify is not needed */
-#ifdef CONFIG_HASH_VERIFY
- if (verify) {
-#else
- if (0) {
-#endif
- if (!argc)
+ algo = find_hash_algo(algo_name);
+ if (!algo) {
+ printf("Unknown hash algorithm '%s'\n", algo_name);
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);
+ }
+ argc -= 2;
+
+ if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
+ puts("HASH_MAX_DIGEST_SIZE exceeded\n");
return 1;
}
- if (memcmp(output, vsum, algo->digest_size) != 0) {
- int i;
+ 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 (flags & HASH_FLAG_VERIFY) {
+#else
+ if (0) {
+#endif
+ 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;
- }
- } else {
- show_hash(algo, addr, len, output);
- printf("\n");
+ printf("\n");
- if (argc)
- store_result(algo, output, *argv);
+ if (argc) {
+ store_result(algo, output, *argv,
+ flags & HASH_FLAG_ENV);
+ }
+ }
+
+ /* Horrible code size hack for boards that just want crc32 */
+ } else {
+ 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 > 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 @@
#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 @@
{ -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 @@
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 @@
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 @@
os_write(1, str, strlen(str));
}
-static int sandbox_serial_getc(void)
+static unsigned int increment_buffer_index(unsigned int index)
{
- char buf;
- ssize_t count;
-
- count = os_read(0, &buf, 1);
- return count == 1 ? buf : 0;
+ return (index + 1) % ARRAY_SIZE(serial_buf);
}
static int sandbox_serial_tstc(void)
{
- return 0;
+ const unsigned int next_index =
+ increment_buffer_index(serial_buf_write);
+ ssize_t count;
+
+ 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_getc(void)
+{
+ 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 = {
diff --git a/fs/fs.c b/fs/fs.c
index 023e7ef..2c9f2c5 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -256,7 +256,6 @@
unsigned long bytes;
unsigned long pos;
int len_read;
- char buf[12];
unsigned long time;
if (argc < 2)
@@ -308,8 +307,7 @@
}
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 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 @@
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 @@
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 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_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 @@
*/
#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 @@
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_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 @@
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 @@
*/
#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 {
diff --git a/net/net.c b/net/net.c
index a40cde1..df94789 100644
--- a/net/net.c
+++ b/net/net.c
@@ -528,15 +528,11 @@
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();