Merge branch 'next' of ../next
[kernel/u-boot.git] / common / cmd_mem.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Memory Functions
26  *
27  * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
28  */
29
30 #include <common.h>
31 #include <command.h>
32 #ifdef CONFIG_HAS_DATAFLASH
33 #include <dataflash.h>
34 #endif
35 #include <watchdog.h>
36
37 #include <u-boot/md5.h>
38 #include <sha1.h>
39
40 #ifdef  CMD_MEM_DEBUG
41 #define PRINTF(fmt,args...)     printf (fmt ,##args)
42 #else
43 #define PRINTF(fmt,args...)
44 #endif
45
46 static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
47
48 /* Display values from last command.
49  * Memory modify remembered values are different from display memory.
50  */
51 uint    dp_last_addr, dp_last_size;
52 uint    dp_last_length = 0x40;
53 uint    mm_last_addr, mm_last_size;
54
55 static  ulong   base_address = 0;
56
57 /* Memory Display
58  *
59  * Syntax:
60  *      md{.b, .w, .l} {addr} {len}
61  */
62 #define DISP_LINE_LEN   16
63 int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
64 {
65         ulong   addr, length;
66 #if defined(CONFIG_HAS_DATAFLASH)
67         ulong   nbytes, linebytes;
68 #endif
69         int     size;
70         int rc = 0;
71
72         /* We use the last specified parameters, unless new ones are
73          * entered.
74          */
75         addr = dp_last_addr;
76         size = dp_last_size;
77         length = dp_last_length;
78
79         if (argc < 2) {
80                 cmd_usage(cmdtp);
81                 return 1;
82         }
83
84         if ((flag & CMD_FLAG_REPEAT) == 0) {
85                 /* New command specified.  Check for a size specification.
86                  * Defaults to long if no or incorrect specification.
87                  */
88                 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
89                         return 1;
90
91                 /* Address is specified since argc > 1
92                 */
93                 addr = simple_strtoul(argv[1], NULL, 16);
94                 addr += base_address;
95
96                 /* If another parameter, it is the length to display.
97                  * Length is the number of objects, not number of bytes.
98                  */
99                 if (argc > 2)
100                         length = simple_strtoul(argv[2], NULL, 16);
101         }
102
103 #if defined(CONFIG_HAS_DATAFLASH)
104         /* Print the lines.
105          *
106          * We buffer all read data, so we can make sure data is read only
107          * once, and all accesses are with the specified bus width.
108          */
109         nbytes = length * size;
110         do {
111                 char    linebuf[DISP_LINE_LEN];
112                 void* p;
113                 linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
114
115                 rc = read_dataflash(addr, (linebytes/size)*size, linebuf);
116                 p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr;
117                 print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size);
118
119                 nbytes -= linebytes;
120                 addr += linebytes;
121                 if (ctrlc()) {
122                         rc = 1;
123                         break;
124                 }
125         } while (nbytes > 0);
126 #else
127
128 # if defined(CONFIG_BLACKFIN)
129         /* See if we're trying to display L1 inst */
130         if (addr_bfin_on_chip_mem(addr)) {
131                 char linebuf[DISP_LINE_LEN];
132                 ulong linebytes, nbytes = length * size;
133                 do {
134                         linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
135                         memcpy(linebuf, (void *)addr, linebytes);
136                         print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size);
137
138                         nbytes -= linebytes;
139                         addr += linebytes;
140                         if (ctrlc()) {
141                                 rc = 1;
142                                 break;
143                         }
144                 } while (nbytes > 0);
145         } else
146 # endif
147
148         {
149                 /* Print the lines. */
150                 print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size);
151                 addr += size*length;
152         }
153 #endif
154
155         dp_last_addr = addr;
156         dp_last_length = length;
157         dp_last_size = size;
158         return (rc);
159 }
160
161 int do_mem_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
162 {
163         return mod_mem (cmdtp, 1, flag, argc, argv);
164 }
165 int do_mem_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
166 {
167         return mod_mem (cmdtp, 0, flag, argc, argv);
168 }
169
170 int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
171 {
172         ulong   addr, writeval, count;
173         int     size;
174
175         if ((argc < 3) || (argc > 4)) {
176                 cmd_usage(cmdtp);
177                 return 1;
178         }
179
180         /* Check for size specification.
181         */
182         if ((size = cmd_get_data_size(argv[0], 4)) < 1)
183                 return 1;
184
185         /* Address is specified since argc > 1
186         */
187         addr = simple_strtoul(argv[1], NULL, 16);
188         addr += base_address;
189
190         /* Get the value to write.
191         */
192         writeval = simple_strtoul(argv[2], NULL, 16);
193
194         /* Count ? */
195         if (argc == 4) {
196                 count = simple_strtoul(argv[3], NULL, 16);
197         } else {
198                 count = 1;
199         }
200
201         while (count-- > 0) {
202                 if (size == 4)
203                         *((ulong  *)addr) = (ulong )writeval;
204                 else if (size == 2)
205                         *((ushort *)addr) = (ushort)writeval;
206                 else
207                         *((u_char *)addr) = (u_char)writeval;
208                 addr += size;
209         }
210         return 0;
211 }
212
213 #ifdef CONFIG_MX_CYCLIC
214 int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
215 {
216         int i;
217         ulong count;
218
219         if (argc < 4) {
220                 cmd_usage(cmdtp);
221                 return 1;
222         }
223
224         count = simple_strtoul(argv[3], NULL, 10);
225
226         for (;;) {
227                 do_mem_md (NULL, 0, 3, argv);
228
229                 /* delay for <count> ms... */
230                 for (i=0; i<count; i++)
231                         udelay (1000);
232
233                 /* check for ctrl-c to abort... */
234                 if (ctrlc()) {
235                         puts("Abort\n");
236                         return 0;
237                 }
238         }
239
240         return 0;
241 }
242
243 int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
244 {
245         int i;
246         ulong count;
247
248         if (argc < 4) {
249                 cmd_usage(cmdtp);
250                 return 1;
251         }
252
253         count = simple_strtoul(argv[3], NULL, 10);
254
255         for (;;) {
256                 do_mem_mw (NULL, 0, 3, argv);
257
258                 /* delay for <count> ms... */
259                 for (i=0; i<count; i++)
260                         udelay (1000);
261
262                 /* check for ctrl-c to abort... */
263                 if (ctrlc()) {
264                         puts("Abort\n");
265                         return 0;
266                 }
267         }
268
269         return 0;
270 }
271 #endif /* CONFIG_MX_CYCLIC */
272
273 int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
274 {
275         ulong   addr1, addr2, count, ngood;
276         int     size;
277         int     rcode = 0;
278
279         if (argc != 4) {
280                 cmd_usage(cmdtp);
281                 return 1;
282         }
283
284         /* Check for size specification.
285         */
286         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
287                 return 1;
288
289         addr1 = simple_strtoul(argv[1], NULL, 16);
290         addr1 += base_address;
291
292         addr2 = simple_strtoul(argv[2], NULL, 16);
293         addr2 += base_address;
294
295         count = simple_strtoul(argv[3], NULL, 16);
296
297 #ifdef CONFIG_HAS_DATAFLASH
298         if (addr_dataflash(addr1) | addr_dataflash(addr2)){
299                 puts ("Comparison with DataFlash space not supported.\n\r");
300                 return 0;
301         }
302 #endif
303
304 #ifdef CONFIG_BLACKFIN
305         if (addr_bfin_on_chip_mem(addr1) || addr_bfin_on_chip_mem(addr2)) {
306                 puts ("Comparison with L1 instruction memory not supported.\n\r");
307                 return 0;
308         }
309 #endif
310
311         ngood = 0;
312
313         while (count-- > 0) {
314                 if (size == 4) {
315                         ulong word1 = *(ulong *)addr1;
316                         ulong word2 = *(ulong *)addr2;
317                         if (word1 != word2) {
318                                 printf("word at 0x%08lx (0x%08lx) "
319                                         "!= word at 0x%08lx (0x%08lx)\n",
320                                         addr1, word1, addr2, word2);
321                                 rcode = 1;
322                                 break;
323                         }
324                 }
325                 else if (size == 2) {
326                         ushort hword1 = *(ushort *)addr1;
327                         ushort hword2 = *(ushort *)addr2;
328                         if (hword1 != hword2) {
329                                 printf("halfword at 0x%08lx (0x%04x) "
330                                         "!= halfword at 0x%08lx (0x%04x)\n",
331                                         addr1, hword1, addr2, hword2);
332                                 rcode = 1;
333                                 break;
334                         }
335                 }
336                 else {
337                         u_char byte1 = *(u_char *)addr1;
338                         u_char byte2 = *(u_char *)addr2;
339                         if (byte1 != byte2) {
340                                 printf("byte at 0x%08lx (0x%02x) "
341                                         "!= byte at 0x%08lx (0x%02x)\n",
342                                         addr1, byte1, addr2, byte2);
343                                 rcode = 1;
344                                 break;
345                         }
346                 }
347                 ngood++;
348                 addr1 += size;
349                 addr2 += size;
350         }
351
352         printf("Total of %ld %s%s were the same\n",
353                 ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
354                 ngood == 1 ? "" : "s");
355         return rcode;
356 }
357
358 int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
359 {
360         ulong   addr, dest, count;
361         int     size;
362
363         if (argc != 4) {
364                 cmd_usage(cmdtp);
365                 return 1;
366         }
367
368         /* Check for size specification.
369         */
370         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
371                 return 1;
372
373         addr = simple_strtoul(argv[1], NULL, 16);
374         addr += base_address;
375
376         dest = simple_strtoul(argv[2], NULL, 16);
377         dest += base_address;
378
379         count = simple_strtoul(argv[3], NULL, 16);
380
381         if (count == 0) {
382                 puts ("Zero length ???\n");
383                 return 1;
384         }
385
386 #ifndef CONFIG_SYS_NO_FLASH
387         /* check if we are copying to Flash */
388         if ( (addr2info(dest) != NULL)
389 #ifdef CONFIG_HAS_DATAFLASH
390            && (!addr_dataflash(dest))
391 #endif
392            ) {
393                 int rc;
394
395                 puts ("Copy to Flash... ");
396
397                 rc = flash_write ((char *)addr, dest, count*size);
398                 if (rc != 0) {
399                         flash_perror (rc);
400                         return (1);
401                 }
402                 puts ("done\n");
403                 return 0;
404         }
405 #endif
406
407 #ifdef CONFIG_HAS_DATAFLASH
408         /* Check if we are copying from RAM or Flash to DataFlash */
409         if (addr_dataflash(dest) && !addr_dataflash(addr)){
410                 int rc;
411
412                 puts ("Copy to DataFlash... ");
413
414                 rc = write_dataflash (dest, addr, count*size);
415
416                 if (rc != 1) {
417                         dataflash_perror (rc);
418                         return (1);
419                 }
420                 puts ("done\n");
421                 return 0;
422         }
423
424         /* Check if we are copying from DataFlash to RAM */
425         if (addr_dataflash(addr) && !addr_dataflash(dest)
426 #ifndef CONFIG_SYS_NO_FLASH
427                                  && (addr2info(dest) == NULL)
428 #endif
429            ){
430                 int rc;
431                 rc = read_dataflash(addr, count * size, (char *) dest);
432                 if (rc != 1) {
433                         dataflash_perror (rc);
434                         return (1);
435                 }
436                 return 0;
437         }
438
439         if (addr_dataflash(addr) && addr_dataflash(dest)){
440                 puts ("Unsupported combination of source/destination.\n\r");
441                 return 1;
442         }
443 #endif
444
445 #ifdef CONFIG_BLACKFIN
446         /* See if we're copying to/from L1 inst */
447         if (addr_bfin_on_chip_mem(dest) || addr_bfin_on_chip_mem(addr)) {
448                 memcpy((void *)dest, (void *)addr, count * size);
449                 return 0;
450         }
451 #endif
452
453         while (count-- > 0) {
454                 if (size == 4)
455                         *((ulong  *)dest) = *((ulong  *)addr);
456                 else if (size == 2)
457                         *((ushort *)dest) = *((ushort *)addr);
458                 else
459                         *((u_char *)dest) = *((u_char *)addr);
460                 addr += size;
461                 dest += size;
462         }
463         return 0;
464 }
465
466 int do_mem_base (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
467 {
468         if (argc > 1) {
469                 /* Set new base address.
470                 */
471                 base_address = simple_strtoul(argv[1], NULL, 16);
472         }
473         /* Print the current base address.
474         */
475         printf("Base Address: 0x%08lx\n", base_address);
476         return 0;
477 }
478
479 int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
480 {
481         ulong   addr, length, i, junk;
482         int     size;
483         volatile uint   *longp;
484         volatile ushort *shortp;
485         volatile u_char *cp;
486
487         if (argc < 3) {
488                 cmd_usage(cmdtp);
489                 return 1;
490         }
491
492         /* Check for a size spefication.
493          * Defaults to long if no or incorrect specification.
494          */
495         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
496                 return 1;
497
498         /* Address is always specified.
499         */
500         addr = simple_strtoul(argv[1], NULL, 16);
501
502         /* Length is the number of objects, not number of bytes.
503         */
504         length = simple_strtoul(argv[2], NULL, 16);
505
506         /* We want to optimize the loops to run as fast as possible.
507          * If we have only one object, just run infinite loops.
508          */
509         if (length == 1) {
510                 if (size == 4) {
511                         longp = (uint *)addr;
512                         for (;;)
513                                 i = *longp;
514                 }
515                 if (size == 2) {
516                         shortp = (ushort *)addr;
517                         for (;;)
518                                 i = *shortp;
519                 }
520                 cp = (u_char *)addr;
521                 for (;;)
522                         i = *cp;
523         }
524
525         if (size == 4) {
526                 for (;;) {
527                         longp = (uint *)addr;
528                         i = length;
529                         while (i-- > 0)
530                                 junk = *longp++;
531                 }
532         }
533         if (size == 2) {
534                 for (;;) {
535                         shortp = (ushort *)addr;
536                         i = length;
537                         while (i-- > 0)
538                                 junk = *shortp++;
539                 }
540         }
541         for (;;) {
542                 cp = (u_char *)addr;
543                 i = length;
544                 while (i-- > 0)
545                         junk = *cp++;
546         }
547 }
548
549 #ifdef CONFIG_LOOPW
550 int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
551 {
552         ulong   addr, length, i, data;
553         int     size;
554         volatile uint   *longp;
555         volatile ushort *shortp;
556         volatile u_char *cp;
557
558         if (argc < 4) {
559                 cmd_usage(cmdtp);
560                 return 1;
561         }
562
563         /* Check for a size spefication.
564          * Defaults to long if no or incorrect specification.
565          */
566         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
567                 return 1;
568
569         /* Address is always specified.
570         */
571         addr = simple_strtoul(argv[1], NULL, 16);
572
573         /* Length is the number of objects, not number of bytes.
574         */
575         length = simple_strtoul(argv[2], NULL, 16);
576
577         /* data to write */
578         data = simple_strtoul(argv[3], NULL, 16);
579
580         /* We want to optimize the loops to run as fast as possible.
581          * If we have only one object, just run infinite loops.
582          */
583         if (length == 1) {
584                 if (size == 4) {
585                         longp = (uint *)addr;
586                         for (;;)
587                                 *longp = data;
588                                         }
589                 if (size == 2) {
590                         shortp = (ushort *)addr;
591                         for (;;)
592                                 *shortp = data;
593                 }
594                 cp = (u_char *)addr;
595                 for (;;)
596                         *cp = data;
597         }
598
599         if (size == 4) {
600                 for (;;) {
601                         longp = (uint *)addr;
602                         i = length;
603                         while (i-- > 0)
604                                 *longp++ = data;
605                 }
606         }
607         if (size == 2) {
608                 for (;;) {
609                         shortp = (ushort *)addr;
610                         i = length;
611                         while (i-- > 0)
612                                 *shortp++ = data;
613                 }
614         }
615         for (;;) {
616                 cp = (u_char *)addr;
617                 i = length;
618                 while (i-- > 0)
619                         *cp++ = data;
620         }
621 }
622 #endif /* CONFIG_LOOPW */
623
624 /*
625  * Perform a memory test. A more complete alternative test can be
626  * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
627  * interrupted by ctrl-c or by a failure of one of the sub-tests.
628  */
629 int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
630 {
631         vu_long *addr, *start, *end;
632         ulong   val;
633         ulong   readback;
634         int     rcode = 0;
635         int iterations = 1;
636         int iteration_limit;
637
638 #if defined(CONFIG_SYS_ALT_MEMTEST)
639         vu_long len;
640         vu_long offset;
641         vu_long test_offset;
642         vu_long pattern;
643         vu_long temp;
644         vu_long anti_pattern;
645         vu_long num_words;
646 #if defined(CONFIG_SYS_MEMTEST_SCRATCH)
647         vu_long *dummy = (vu_long*)CONFIG_SYS_MEMTEST_SCRATCH;
648 #else
649         vu_long *dummy = 0;     /* yes, this is address 0x0, not NULL */
650 #endif
651         int     j;
652
653         static const ulong bitpattern[] = {
654                 0x00000001,     /* single bit */
655                 0x00000003,     /* two adjacent bits */
656                 0x00000007,     /* three adjacent bits */
657                 0x0000000F,     /* four adjacent bits */
658                 0x00000005,     /* two non-adjacent bits */
659                 0x00000015,     /* three non-adjacent bits */
660                 0x00000055,     /* four non-adjacent bits */
661                 0xaaaaaaaa,     /* alternating 1/0 */
662         };
663 #else
664         ulong   incr;
665         ulong   pattern;
666 #endif
667
668         if (argc > 1)
669                 start = (ulong *)simple_strtoul(argv[1], NULL, 16);
670         else
671                 start = (ulong *)CONFIG_SYS_MEMTEST_START;
672
673         if (argc > 2)
674                 end = (ulong *)simple_strtoul(argv[2], NULL, 16);
675         else
676                 end = (ulong *)(CONFIG_SYS_MEMTEST_END);
677
678         if (argc > 3)
679                 pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
680         else
681                 pattern = 0;
682
683         if (argc > 4)
684                 iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16);
685         else
686                 iteration_limit = 0;
687
688 #if defined(CONFIG_SYS_ALT_MEMTEST)
689         printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
690         PRINTF("%s:%d: start 0x%p end 0x%p\n",
691                 __FUNCTION__, __LINE__, start, end);
692
693         for (;;) {
694                 if (ctrlc()) {
695                         putc ('\n');
696                         return 1;
697                 }
698
699
700                 if (iteration_limit && iterations > iteration_limit) {
701                         printf("Tested %d iteration(s) without errors.\n",
702                                 iterations-1);
703                         return 0;
704                 }
705
706                 printf("Iteration: %6d\r", iterations);
707                 PRINTF("\n");
708                 iterations++;
709
710                 /*
711                  * Data line test: write a pattern to the first
712                  * location, write the 1's complement to a 'parking'
713                  * address (changes the state of the data bus so a
714                  * floating bus doen't give a false OK), and then
715                  * read the value back. Note that we read it back
716                  * into a variable because the next time we read it,
717                  * it might be right (been there, tough to explain to
718                  * the quality guys why it prints a failure when the
719                  * "is" and "should be" are obviously the same in the
720                  * error message).
721                  *
722                  * Rather than exhaustively testing, we test some
723                  * patterns by shifting '1' bits through a field of
724                  * '0's and '0' bits through a field of '1's (i.e.
725                  * pattern and ~pattern).
726                  */
727                 addr = start;
728                 for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
729                     val = bitpattern[j];
730                     for(; val != 0; val <<= 1) {
731                         *addr  = val;
732                         *dummy  = ~val; /* clear the test data off of the bus */
733                         readback = *addr;
734                         if(readback != val) {
735                              printf ("FAILURE (data line): "
736                                 "expected %08lx, actual %08lx\n",
737                                           val, readback);
738                         }
739                         *addr  = ~val;
740                         *dummy  = val;
741                         readback = *addr;
742                         if(readback != ~val) {
743                             printf ("FAILURE (data line): "
744                                 "Is %08lx, should be %08lx\n",
745                                         readback, ~val);
746                         }
747                     }
748                 }
749
750                 /*
751                  * Based on code whose Original Author and Copyright
752                  * information follows: Copyright (c) 1998 by Michael
753                  * Barr. This software is placed into the public
754                  * domain and may be used for any purpose. However,
755                  * this notice must not be changed or removed and no
756                  * warranty is either expressed or implied by its
757                  * publication or distribution.
758                  */
759
760                 /*
761                  * Address line test
762                  *
763                  * Description: Test the address bus wiring in a
764                  *              memory region by performing a walking
765                  *              1's test on the relevant bits of the
766                  *              address and checking for aliasing.
767                  *              This test will find single-bit
768                  *              address failures such as stuck -high,
769                  *              stuck-low, and shorted pins. The base
770                  *              address and size of the region are
771                  *              selected by the caller.
772                  *
773                  * Notes:       For best results, the selected base
774                  *              address should have enough LSB 0's to
775                  *              guarantee single address bit changes.
776                  *              For example, to test a 64-Kbyte
777                  *              region, select a base address on a
778                  *              64-Kbyte boundary. Also, select the
779                  *              region size as a power-of-two if at
780                  *              all possible.
781                  *
782                  * Returns:     0 if the test succeeds, 1 if the test fails.
783                  */
784                 len = ((ulong)end - (ulong)start)/sizeof(vu_long);
785                 pattern = (vu_long) 0xaaaaaaaa;
786                 anti_pattern = (vu_long) 0x55555555;
787
788                 PRINTF("%s:%d: length = 0x%.8lx\n",
789                         __FUNCTION__, __LINE__,
790                         len);
791                 /*
792                  * Write the default pattern at each of the
793                  * power-of-two offsets.
794                  */
795                 for (offset = 1; offset < len; offset <<= 1) {
796                         start[offset] = pattern;
797                 }
798
799                 /*
800                  * Check for address bits stuck high.
801                  */
802                 test_offset = 0;
803                 start[test_offset] = anti_pattern;
804
805                 for (offset = 1; offset < len; offset <<= 1) {
806                     temp = start[offset];
807                     if (temp != pattern) {
808                         printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
809                                 " expected 0x%.8lx, actual 0x%.8lx\n",
810                                 (ulong)&start[offset], pattern, temp);
811                         return 1;
812                     }
813                 }
814                 start[test_offset] = pattern;
815                 WATCHDOG_RESET();
816
817                 /*
818                  * Check for addr bits stuck low or shorted.
819                  */
820                 for (test_offset = 1; test_offset < len; test_offset <<= 1) {
821                     start[test_offset] = anti_pattern;
822
823                     for (offset = 1; offset < len; offset <<= 1) {
824                         temp = start[offset];
825                         if ((temp != pattern) && (offset != test_offset)) {
826                             printf ("\nFAILURE: Address bit stuck low or shorted @"
827                                 " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
828                                 (ulong)&start[offset], pattern, temp);
829                             return 1;
830                         }
831                     }
832                     start[test_offset] = pattern;
833                 }
834
835                 /*
836                  * Description: Test the integrity of a physical
837                  *              memory device by performing an
838                  *              increment/decrement test over the
839                  *              entire region. In the process every
840                  *              storage bit in the device is tested
841                  *              as a zero and a one. The base address
842                  *              and the size of the region are
843                  *              selected by the caller.
844                  *
845                  * Returns:     0 if the test succeeds, 1 if the test fails.
846                  */
847                 num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
848
849                 /*
850                  * Fill memory with a known pattern.
851                  */
852                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
853                         WATCHDOG_RESET();
854                         start[offset] = pattern;
855                 }
856
857                 /*
858                  * Check each location and invert it for the second pass.
859                  */
860                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
861                     WATCHDOG_RESET();
862                     temp = start[offset];
863                     if (temp != pattern) {
864                         printf ("\nFAILURE (read/write) @ 0x%.8lx:"
865                                 " expected 0x%.8lx, actual 0x%.8lx)\n",
866                                 (ulong)&start[offset], pattern, temp);
867                         return 1;
868                     }
869
870                     anti_pattern = ~pattern;
871                     start[offset] = anti_pattern;
872                 }
873
874                 /*
875                  * Check each location for the inverted pattern and zero it.
876                  */
877                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
878                     WATCHDOG_RESET();
879                     anti_pattern = ~pattern;
880                     temp = start[offset];
881                     if (temp != anti_pattern) {
882                         printf ("\nFAILURE (read/write): @ 0x%.8lx:"
883                                 " expected 0x%.8lx, actual 0x%.8lx)\n",
884                                 (ulong)&start[offset], anti_pattern, temp);
885                         return 1;
886                     }
887                     start[offset] = 0;
888                 }
889         }
890
891 #else /* The original, quickie test */
892         incr = 1;
893         for (;;) {
894                 if (ctrlc()) {
895                         putc ('\n');
896                         return 1;
897                 }
898
899                 if (iteration_limit && iterations > iteration_limit) {
900                         printf("Tested %d iteration(s) without errors.\n",
901                                 iterations-1);
902                         return 0;
903                 }
904                 ++iterations;
905
906                 printf ("\rPattern %08lX  Writing..."
907                         "%12s"
908                         "\b\b\b\b\b\b\b\b\b\b",
909                         pattern, "");
910
911                 for (addr=start,val=pattern; addr<end; addr++) {
912                         WATCHDOG_RESET();
913                         *addr = val;
914                         val  += incr;
915                 }
916
917                 puts ("Reading...");
918
919                 for (addr=start,val=pattern; addr<end; addr++) {
920                         WATCHDOG_RESET();
921                         readback = *addr;
922                         if (readback != val) {
923                                 printf ("\nMem error @ 0x%08X: "
924                                         "found %08lX, expected %08lX\n",
925                                         (uint)addr, readback, val);
926                                 rcode = 1;
927                         }
928                         val += incr;
929                 }
930
931                 /*
932                  * Flip the pattern each time to make lots of zeros and
933                  * then, the next time, lots of ones.  We decrement
934                  * the "negative" patterns and increment the "positive"
935                  * patterns to preserve this feature.
936                  */
937                 if(pattern & 0x80000000) {
938                         pattern = -pattern;     /* complement & increment */
939                 }
940                 else {
941                         pattern = ~pattern;
942                 }
943                 incr = -incr;
944         }
945 #endif
946         return rcode;
947 }
948
949
950 /* Modify memory.
951  *
952  * Syntax:
953  *      mm{.b, .w, .l} {addr}
954  *      nm{.b, .w, .l} {addr}
955  */
956 static int
957 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
958 {
959         ulong   addr, i;
960         int     nbytes, size;
961         extern char console_buffer[];
962
963         if (argc != 2) {
964                 cmd_usage(cmdtp);
965                 return 1;
966         }
967
968 #ifdef CONFIG_BOOT_RETRY_TIME
969         reset_cmd_timeout();    /* got a good command to get here */
970 #endif
971         /* We use the last specified parameters, unless new ones are
972          * entered.
973          */
974         addr = mm_last_addr;
975         size = mm_last_size;
976
977         if ((flag & CMD_FLAG_REPEAT) == 0) {
978                 /* New command specified.  Check for a size specification.
979                  * Defaults to long if no or incorrect specification.
980                  */
981                 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
982                         return 1;
983
984                 /* Address is specified since argc > 1
985                 */
986                 addr = simple_strtoul(argv[1], NULL, 16);
987                 addr += base_address;
988         }
989
990 #ifdef CONFIG_HAS_DATAFLASH
991         if (addr_dataflash(addr)){
992                 puts ("Can't modify DataFlash in place. Use cp instead.\n\r");
993                 return 0;
994         }
995 #endif
996
997 #ifdef CONFIG_BLACKFIN
998         if (addr_bfin_on_chip_mem(addr)) {
999                 puts ("Can't modify L1 instruction in place. Use cp instead.\n\r");
1000                 return 0;
1001         }
1002 #endif
1003
1004         /* Print the address, followed by value.  Then accept input for
1005          * the next value.  A non-converted value exits.
1006          */
1007         do {
1008                 printf("%08lx:", addr);
1009                 if (size == 4)
1010                         printf(" %08x", *((uint   *)addr));
1011                 else if (size == 2)
1012                         printf(" %04x", *((ushort *)addr));
1013                 else
1014                         printf(" %02x", *((u_char *)addr));
1015
1016                 nbytes = readline (" ? ");
1017                 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
1018                         /* <CR> pressed as only input, don't modify current
1019                          * location and move to next. "-" pressed will go back.
1020                          */
1021                         if (incrflag)
1022                                 addr += nbytes ? -size : size;
1023                         nbytes = 1;
1024 #ifdef CONFIG_BOOT_RETRY_TIME
1025                         reset_cmd_timeout(); /* good enough to not time out */
1026 #endif
1027                 }
1028 #ifdef CONFIG_BOOT_RETRY_TIME
1029                 else if (nbytes == -2) {
1030                         break;  /* timed out, exit the command  */
1031                 }
1032 #endif
1033                 else {
1034                         char *endp;
1035                         i = simple_strtoul(console_buffer, &endp, 16);
1036                         nbytes = endp - console_buffer;
1037                         if (nbytes) {
1038 #ifdef CONFIG_BOOT_RETRY_TIME
1039                                 /* good enough to not time out
1040                                  */
1041                                 reset_cmd_timeout();
1042 #endif
1043                                 if (size == 4)
1044                                         *((uint   *)addr) = i;
1045                                 else if (size == 2)
1046                                         *((ushort *)addr) = i;
1047                                 else
1048                                         *((u_char *)addr) = i;
1049                                 if (incrflag)
1050                                         addr += size;
1051                         }
1052                 }
1053         } while (nbytes);
1054
1055         mm_last_addr = addr;
1056         mm_last_size = size;
1057         return 0;
1058 }
1059
1060 #ifndef CONFIG_CRC32_VERIFY
1061
1062 int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1063 {
1064         ulong addr, length;
1065         ulong crc;
1066         ulong *ptr;
1067
1068         if (argc < 3) {
1069                 cmd_usage(cmdtp);
1070                 return 1;
1071         }
1072
1073         addr = simple_strtoul (argv[1], NULL, 16);
1074         addr += base_address;
1075
1076         length = simple_strtoul (argv[2], NULL, 16);
1077
1078         crc = crc32 (0, (const uchar *) addr, length);
1079
1080         printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
1081                         addr, addr + length - 1, crc);
1082
1083         if (argc > 3) {
1084                 ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
1085                 *ptr = crc;
1086         }
1087
1088         return 0;
1089 }
1090
1091 #else   /* CONFIG_CRC32_VERIFY */
1092
1093 int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1094 {
1095         ulong addr, length;
1096         ulong crc;
1097         ulong *ptr;
1098         ulong vcrc;
1099         int verify;
1100         int ac;
1101         char **av;
1102
1103         if (argc < 3) {
1104   usage:
1105                 cmd_usage(cmdtp);
1106                 return 1;
1107         }
1108
1109         av = argv + 1;
1110         ac = argc - 1;
1111         if (strcmp(*av, "-v") == 0) {
1112                 verify = 1;
1113                 av++;
1114                 ac--;
1115                 if (ac < 3)
1116                         goto usage;
1117         } else
1118                 verify = 0;
1119
1120         addr = simple_strtoul(*av++, NULL, 16);
1121         addr += base_address;
1122         length = simple_strtoul(*av++, NULL, 16);
1123
1124         crc = crc32(0, (const uchar *) addr, length);
1125
1126         if (!verify) {
1127                 printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
1128                                 addr, addr + length - 1, crc);
1129                 if (ac > 2) {
1130                         ptr = (ulong *) simple_strtoul (*av++, NULL, 16);
1131                         *ptr = crc;
1132                 }
1133         } else {
1134                 vcrc = simple_strtoul(*av++, NULL, 16);
1135                 if (vcrc != crc) {
1136                         printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n",
1137                                         addr, addr + length - 1, crc, vcrc);
1138                         return 1;
1139                 }
1140         }
1141
1142         return 0;
1143
1144 }
1145 #endif  /* CONFIG_CRC32_VERIFY */
1146
1147 #ifdef CONFIG_CMD_MD5SUM
1148 int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1149 {
1150         unsigned long addr, len;
1151         unsigned int i;
1152         u8 output[16];
1153
1154         if (argc < 3) {
1155                 cmd_usage(cmdtp);
1156                 return 1;
1157         }
1158
1159         addr = simple_strtoul(argv[1], NULL, 16);
1160         len = simple_strtoul(argv[2], NULL, 16);
1161
1162         md5((unsigned char *) addr, len, output);
1163         printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1);
1164         for (i = 0; i < 16; i++)
1165                 printf("%02x", output[i]);
1166         printf("\n");
1167
1168         return 0;
1169 }
1170 #endif
1171
1172 #ifdef CONFIG_CMD_SHA1
1173 int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1174 {
1175         unsigned long addr, len;
1176         unsigned int i;
1177         u8 output[20];
1178
1179         if (argc < 3) {
1180                 cmd_usage(cmdtp);
1181                 return 1;
1182         }
1183
1184         addr = simple_strtoul(argv[1], NULL, 16);
1185         len = simple_strtoul(argv[2], NULL, 16);
1186
1187         sha1_csum((unsigned char *) addr, len, output);
1188         printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1);
1189         for (i = 0; i < 20; i++)
1190                 printf("%02x", output[i]);
1191         printf("\n");
1192
1193         return 0;
1194 }
1195 #endif
1196
1197 #ifdef CONFIG_CMD_UNZIP
1198 int  gunzip (void *, int, unsigned char *, unsigned long *);
1199
1200 int do_unzip ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1201 {
1202         unsigned long src, dst;
1203         unsigned long src_len = ~0UL, dst_len = ~0UL;
1204
1205         switch (argc) {
1206                 case 4:
1207                         dst_len = simple_strtoul(argv[3], NULL, 16);
1208                         /* fall through */
1209                 case 3:
1210                         src = simple_strtoul(argv[1], NULL, 16);
1211                         dst = simple_strtoul(argv[2], NULL, 16);
1212                         break;
1213                 default:
1214                         cmd_usage(cmdtp);
1215                         return 1;
1216         }
1217
1218         return !!gunzip((void *) dst, dst_len, (void *) src, &src_len);
1219 }
1220 #endif /* CONFIG_CMD_UNZIP */
1221
1222
1223 /**************************************************/
1224 U_BOOT_CMD(
1225         md,     3,      1,      do_mem_md,
1226         "memory display",
1227         "[.b, .w, .l] address [# of objects]"
1228 );
1229
1230
1231 U_BOOT_CMD(
1232         mm,     2,      1,      do_mem_mm,
1233         "memory modify (auto-incrementing address)",
1234         "[.b, .w, .l] address"
1235 );
1236
1237
1238 U_BOOT_CMD(
1239         nm,     2,      1,      do_mem_nm,
1240         "memory modify (constant address)",
1241         "[.b, .w, .l] address"
1242 );
1243
1244 U_BOOT_CMD(
1245         mw,     4,      1,      do_mem_mw,
1246         "memory write (fill)",
1247         "[.b, .w, .l] address value [count]"
1248 );
1249
1250 U_BOOT_CMD(
1251         cp,     4,      1,      do_mem_cp,
1252         "memory copy",
1253         "[.b, .w, .l] source target count"
1254 );
1255
1256 U_BOOT_CMD(
1257         cmp,    4,      1,      do_mem_cmp,
1258         "memory compare",
1259         "[.b, .w, .l] addr1 addr2 count"
1260 );
1261
1262 #ifndef CONFIG_CRC32_VERIFY
1263
1264 U_BOOT_CMD(
1265         crc32,  4,      1,      do_mem_crc,
1266         "checksum calculation",
1267         "address count [addr]\n    - compute CRC32 checksum [save at addr]"
1268 );
1269
1270 #else   /* CONFIG_CRC32_VERIFY */
1271
1272 U_BOOT_CMD(
1273         crc32,  5,      1,      do_mem_crc,
1274         "checksum calculation",
1275         "address count [addr]\n    - compute CRC32 checksum [save at addr]\n"
1276         "-v address count crc\n    - verify crc of memory area"
1277 );
1278
1279 #endif  /* CONFIG_CRC32_VERIFY */
1280
1281 U_BOOT_CMD(
1282         base,   2,      1,      do_mem_base,
1283         "print or set address offset",
1284         "\n    - print address offset for memory commands\n"
1285         "base off\n    - set address offset for memory commands to 'off'"
1286 );
1287
1288 U_BOOT_CMD(
1289         loop,   3,      1,      do_mem_loop,
1290         "infinite loop on address range",
1291         "[.b, .w, .l] address number_of_objects"
1292 );
1293
1294 #ifdef CONFIG_LOOPW
1295 U_BOOT_CMD(
1296         loopw,  4,      1,      do_mem_loopw,
1297         "infinite write loop on address range",
1298         "[.b, .w, .l] address number_of_objects data_to_write"
1299 );
1300 #endif /* CONFIG_LOOPW */
1301
1302 U_BOOT_CMD(
1303         mtest,  5,      1,      do_mem_mtest,
1304         "simple RAM read/write test",
1305         "[start [end [pattern [iterations]]]]"
1306 );
1307
1308 #ifdef CONFIG_MX_CYCLIC
1309 U_BOOT_CMD(
1310         mdc,    4,      1,      do_mem_mdc,
1311         "memory display cyclic",
1312         "[.b, .w, .l] address count delay(ms)"
1313 );
1314
1315 U_BOOT_CMD(
1316         mwc,    4,      1,      do_mem_mwc,
1317         "memory write cyclic",
1318         "[.b, .w, .l] address value delay(ms)"
1319 );
1320 #endif /* CONFIG_MX_CYCLIC */
1321
1322 #ifdef CONFIG_CMD_MD5SUM
1323 U_BOOT_CMD(
1324         md5sum, 3,      1,      do_md5sum,
1325         "compute MD5 message digest",
1326         "address count"
1327 );
1328 #endif
1329
1330 #ifdef CONFIG_CMD_SHA1SUM
1331 U_BOOT_CMD(
1332         sha1sum,        3,      1,      do_sha1sum,
1333         "compute SHA1 message digest",
1334         "address count"
1335 );
1336 #endif /* CONFIG_CMD_SHA1 */
1337
1338 #ifdef CONFIG_CMD_UNZIP
1339 U_BOOT_CMD(
1340         unzip,  4,      1,      do_unzip,
1341         "unzip a memory region",
1342         "srcaddr dstaddr [dstsize]"
1343 );
1344 #endif /* CONFIG_CMD_UNZIP */