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