setenv(): Delete 0-length environment variables
[platform/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         ulong   errs = 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) with %lu errors.\n",
702                                 iterations-1, errs);
703                         return errs != 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                             errs++;
739                             if (ctrlc()) {
740                                 putc ('\n');
741                                 return 1;
742                             }
743                         }
744                         *addr  = ~val;
745                         *dummy  = val;
746                         readback = *addr;
747                         if(readback != ~val) {
748                             printf ("FAILURE (data line): "
749                                 "Is %08lx, should be %08lx\n",
750                                         readback, ~val);
751                             errs++;
752                             if (ctrlc()) {
753                                 putc ('\n');
754                                 return 1;
755                             }
756                         }
757                     }
758                 }
759
760                 /*
761                  * Based on code whose Original Author and Copyright
762                  * information follows: Copyright (c) 1998 by Michael
763                  * Barr. This software is placed into the public
764                  * domain and may be used for any purpose. However,
765                  * this notice must not be changed or removed and no
766                  * warranty is either expressed or implied by its
767                  * publication or distribution.
768                  */
769
770                 /*
771                  * Address line test
772                  *
773                  * Description: Test the address bus wiring in a
774                  *              memory region by performing a walking
775                  *              1's test on the relevant bits of the
776                  *              address and checking for aliasing.
777                  *              This test will find single-bit
778                  *              address failures such as stuck -high,
779                  *              stuck-low, and shorted pins. The base
780                  *              address and size of the region are
781                  *              selected by the caller.
782                  *
783                  * Notes:       For best results, the selected base
784                  *              address should have enough LSB 0's to
785                  *              guarantee single address bit changes.
786                  *              For example, to test a 64-Kbyte
787                  *              region, select a base address on a
788                  *              64-Kbyte boundary. Also, select the
789                  *              region size as a power-of-two if at
790                  *              all possible.
791                  *
792                  * Returns:     0 if the test succeeds, 1 if the test fails.
793                  */
794                 len = ((ulong)end - (ulong)start)/sizeof(vu_long);
795                 pattern = (vu_long) 0xaaaaaaaa;
796                 anti_pattern = (vu_long) 0x55555555;
797
798                 PRINTF("%s:%d: length = 0x%.8lx\n",
799                         __FUNCTION__, __LINE__,
800                         len);
801                 /*
802                  * Write the default pattern at each of the
803                  * power-of-two offsets.
804                  */
805                 for (offset = 1; offset < len; offset <<= 1) {
806                         start[offset] = pattern;
807                 }
808
809                 /*
810                  * Check for address bits stuck high.
811                  */
812                 test_offset = 0;
813                 start[test_offset] = anti_pattern;
814
815                 for (offset = 1; offset < len; offset <<= 1) {
816                     temp = start[offset];
817                     if (temp != pattern) {
818                         printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
819                                 " expected 0x%.8lx, actual 0x%.8lx\n",
820                                 (ulong)&start[offset], pattern, temp);
821                         errs++;
822                         if (ctrlc()) {
823                             putc ('\n');
824                             return 1;
825                         }
826                     }
827                 }
828                 start[test_offset] = pattern;
829                 WATCHDOG_RESET();
830
831                 /*
832                  * Check for addr bits stuck low or shorted.
833                  */
834                 for (test_offset = 1; test_offset < len; test_offset <<= 1) {
835                     start[test_offset] = anti_pattern;
836
837                     for (offset = 1; offset < len; offset <<= 1) {
838                         temp = start[offset];
839                         if ((temp != pattern) && (offset != test_offset)) {
840                             printf ("\nFAILURE: Address bit stuck low or shorted @"
841                                 " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
842                                 (ulong)&start[offset], pattern, temp);
843                             errs++;
844                             if (ctrlc()) {
845                                 putc ('\n');
846                                 return 1;
847                             }
848                         }
849                     }
850                     start[test_offset] = pattern;
851                 }
852
853                 /*
854                  * Description: Test the integrity of a physical
855                  *              memory device by performing an
856                  *              increment/decrement test over the
857                  *              entire region. In the process every
858                  *              storage bit in the device is tested
859                  *              as a zero and a one. The base address
860                  *              and the size of the region are
861                  *              selected by the caller.
862                  *
863                  * Returns:     0 if the test succeeds, 1 if the test fails.
864                  */
865                 num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
866
867                 /*
868                  * Fill memory with a known pattern.
869                  */
870                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
871                         WATCHDOG_RESET();
872                         start[offset] = pattern;
873                 }
874
875                 /*
876                  * Check each location and invert it for the second pass.
877                  */
878                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
879                     WATCHDOG_RESET();
880                     temp = start[offset];
881                     if (temp != pattern) {
882                         printf ("\nFAILURE (read/write) @ 0x%.8lx:"
883                                 " expected 0x%.8lx, actual 0x%.8lx)\n",
884                                 (ulong)&start[offset], pattern, temp);
885                         errs++;
886                         if (ctrlc()) {
887                             putc ('\n');
888                             return 1;
889                         }
890                     }
891
892                     anti_pattern = ~pattern;
893                     start[offset] = anti_pattern;
894                 }
895
896                 /*
897                  * Check each location for the inverted pattern and zero it.
898                  */
899                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
900                     WATCHDOG_RESET();
901                     anti_pattern = ~pattern;
902                     temp = start[offset];
903                     if (temp != anti_pattern) {
904                         printf ("\nFAILURE (read/write): @ 0x%.8lx:"
905                                 " expected 0x%.8lx, actual 0x%.8lx)\n",
906                                 (ulong)&start[offset], anti_pattern, temp);
907                         errs++;
908                         if (ctrlc()) {
909                             putc ('\n');
910                             return 1;
911                         }
912                     }
913                     start[offset] = 0;
914                 }
915         }
916
917 #else /* The original, quickie test */
918         incr = 1;
919         for (;;) {
920                 if (ctrlc()) {
921                         putc ('\n');
922                         return 1;
923                 }
924
925                 if (iteration_limit && iterations > iteration_limit) {
926                         printf("Tested %d iteration(s) with %lu errors.\n",
927                                 iterations-1, errs);
928                         return errs != 0;
929                 }
930                 ++iterations;
931
932                 printf ("\rPattern %08lX  Writing..."
933                         "%12s"
934                         "\b\b\b\b\b\b\b\b\b\b",
935                         pattern, "");
936
937                 for (addr=start,val=pattern; addr<end; addr++) {
938                         WATCHDOG_RESET();
939                         *addr = val;
940                         val  += incr;
941                 }
942
943                 puts ("Reading...");
944
945                 for (addr=start,val=pattern; addr<end; addr++) {
946                         WATCHDOG_RESET();
947                         readback = *addr;
948                         if (readback != val) {
949                                 printf ("\nMem error @ 0x%08X: "
950                                         "found %08lX, expected %08lX\n",
951                                         (uint)addr, readback, val);
952                                 errs++;
953                                 if (ctrlc()) {
954                                         putc ('\n');
955                                         return 1;
956                                 }
957                         }
958                         val += incr;
959                 }
960
961                 /*
962                  * Flip the pattern each time to make lots of zeros and
963                  * then, the next time, lots of ones.  We decrement
964                  * the "negative" patterns and increment the "positive"
965                  * patterns to preserve this feature.
966                  */
967                 if(pattern & 0x80000000) {
968                         pattern = -pattern;     /* complement & increment */
969                 }
970                 else {
971                         pattern = ~pattern;
972                 }
973                 incr = -incr;
974         }
975 #endif
976         return 0;       /* not reached */
977 }
978
979
980 /* Modify memory.
981  *
982  * Syntax:
983  *      mm{.b, .w, .l} {addr}
984  *      nm{.b, .w, .l} {addr}
985  */
986 static int
987 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
988 {
989         ulong   addr, i;
990         int     nbytes, size;
991         extern char console_buffer[];
992
993         if (argc != 2) {
994                 cmd_usage(cmdtp);
995                 return 1;
996         }
997
998 #ifdef CONFIG_BOOT_RETRY_TIME
999         reset_cmd_timeout();    /* got a good command to get here */
1000 #endif
1001         /* We use the last specified parameters, unless new ones are
1002          * entered.
1003          */
1004         addr = mm_last_addr;
1005         size = mm_last_size;
1006
1007         if ((flag & CMD_FLAG_REPEAT) == 0) {
1008                 /* New command specified.  Check for a size specification.
1009                  * Defaults to long if no or incorrect specification.
1010                  */
1011                 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
1012                         return 1;
1013
1014                 /* Address is specified since argc > 1
1015                 */
1016                 addr = simple_strtoul(argv[1], NULL, 16);
1017                 addr += base_address;
1018         }
1019
1020 #ifdef CONFIG_HAS_DATAFLASH
1021         if (addr_dataflash(addr)){
1022                 puts ("Can't modify DataFlash in place. Use cp instead.\n\r");
1023                 return 0;
1024         }
1025 #endif
1026
1027 #ifdef CONFIG_BLACKFIN
1028         if (addr_bfin_on_chip_mem(addr)) {
1029                 puts ("Can't modify L1 instruction in place. Use cp instead.\n\r");
1030                 return 0;
1031         }
1032 #endif
1033
1034         /* Print the address, followed by value.  Then accept input for
1035          * the next value.  A non-converted value exits.
1036          */
1037         do {
1038                 printf("%08lx:", addr);
1039                 if (size == 4)
1040                         printf(" %08x", *((uint   *)addr));
1041                 else if (size == 2)
1042                         printf(" %04x", *((ushort *)addr));
1043                 else
1044                         printf(" %02x", *((u_char *)addr));
1045
1046                 nbytes = readline (" ? ");
1047                 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
1048                         /* <CR> pressed as only input, don't modify current
1049                          * location and move to next. "-" pressed will go back.
1050                          */
1051                         if (incrflag)
1052                                 addr += nbytes ? -size : size;
1053                         nbytes = 1;
1054 #ifdef CONFIG_BOOT_RETRY_TIME
1055                         reset_cmd_timeout(); /* good enough to not time out */
1056 #endif
1057                 }
1058 #ifdef CONFIG_BOOT_RETRY_TIME
1059                 else if (nbytes == -2) {
1060                         break;  /* timed out, exit the command  */
1061                 }
1062 #endif
1063                 else {
1064                         char *endp;
1065                         i = simple_strtoul(console_buffer, &endp, 16);
1066                         nbytes = endp - console_buffer;
1067                         if (nbytes) {
1068 #ifdef CONFIG_BOOT_RETRY_TIME
1069                                 /* good enough to not time out
1070                                  */
1071                                 reset_cmd_timeout();
1072 #endif
1073                                 if (size == 4)
1074                                         *((uint   *)addr) = i;
1075                                 else if (size == 2)
1076                                         *((ushort *)addr) = i;
1077                                 else
1078                                         *((u_char *)addr) = i;
1079                                 if (incrflag)
1080                                         addr += size;
1081                         }
1082                 }
1083         } while (nbytes);
1084
1085         mm_last_addr = addr;
1086         mm_last_size = size;
1087         return 0;
1088 }
1089
1090 #ifndef CONFIG_CRC32_VERIFY
1091
1092 int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1093 {
1094         ulong addr, length;
1095         ulong crc;
1096         ulong *ptr;
1097
1098         if (argc < 3) {
1099                 cmd_usage(cmdtp);
1100                 return 1;
1101         }
1102
1103         addr = simple_strtoul (argv[1], NULL, 16);
1104         addr += base_address;
1105
1106         length = simple_strtoul (argv[2], NULL, 16);
1107
1108         crc = crc32 (0, (const uchar *) addr, length);
1109
1110         printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
1111                         addr, addr + length - 1, crc);
1112
1113         if (argc > 3) {
1114                 ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
1115                 *ptr = crc;
1116         }
1117
1118         return 0;
1119 }
1120
1121 #else   /* CONFIG_CRC32_VERIFY */
1122
1123 int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1124 {
1125         ulong addr, length;
1126         ulong crc;
1127         ulong *ptr;
1128         ulong vcrc;
1129         int verify;
1130         int ac;
1131         char **av;
1132
1133         if (argc < 3) {
1134   usage:
1135                 cmd_usage(cmdtp);
1136                 return 1;
1137         }
1138
1139         av = argv + 1;
1140         ac = argc - 1;
1141         if (strcmp(*av, "-v") == 0) {
1142                 verify = 1;
1143                 av++;
1144                 ac--;
1145                 if (ac < 3)
1146                         goto usage;
1147         } else
1148                 verify = 0;
1149
1150         addr = simple_strtoul(*av++, NULL, 16);
1151         addr += base_address;
1152         length = simple_strtoul(*av++, NULL, 16);
1153
1154         crc = crc32(0, (const uchar *) addr, length);
1155
1156         if (!verify) {
1157                 printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
1158                                 addr, addr + length - 1, crc);
1159                 if (ac > 2) {
1160                         ptr = (ulong *) simple_strtoul (*av++, NULL, 16);
1161                         *ptr = crc;
1162                 }
1163         } else {
1164                 vcrc = simple_strtoul(*av++, NULL, 16);
1165                 if (vcrc != crc) {
1166                         printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n",
1167                                         addr, addr + length - 1, crc, vcrc);
1168                         return 1;
1169                 }
1170         }
1171
1172         return 0;
1173
1174 }
1175 #endif  /* CONFIG_CRC32_VERIFY */
1176
1177 #ifdef CONFIG_CMD_MD5SUM
1178 int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1179 {
1180         unsigned long addr, len;
1181         unsigned int i;
1182         u8 output[16];
1183
1184         if (argc < 3) {
1185                 cmd_usage(cmdtp);
1186                 return 1;
1187         }
1188
1189         addr = simple_strtoul(argv[1], NULL, 16);
1190         len = simple_strtoul(argv[2], NULL, 16);
1191
1192         md5((unsigned char *) addr, len, output);
1193         printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1);
1194         for (i = 0; i < 16; i++)
1195                 printf("%02x", output[i]);
1196         printf("\n");
1197
1198         return 0;
1199 }
1200 #endif
1201
1202 #ifdef CONFIG_CMD_SHA1
1203 int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1204 {
1205         unsigned long addr, len;
1206         unsigned int i;
1207         u8 output[20];
1208
1209         if (argc < 3) {
1210                 cmd_usage(cmdtp);
1211                 return 1;
1212         }
1213
1214         addr = simple_strtoul(argv[1], NULL, 16);
1215         len = simple_strtoul(argv[2], NULL, 16);
1216
1217         sha1_csum((unsigned char *) addr, len, output);
1218         printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1);
1219         for (i = 0; i < 20; i++)
1220                 printf("%02x", output[i]);
1221         printf("\n");
1222
1223         return 0;
1224 }
1225 #endif
1226
1227 #ifdef CONFIG_CMD_UNZIP
1228 int  gunzip (void *, int, unsigned char *, unsigned long *);
1229
1230 int do_unzip ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1231 {
1232         unsigned long src, dst;
1233         unsigned long src_len = ~0UL, dst_len = ~0UL;
1234
1235         switch (argc) {
1236                 case 4:
1237                         dst_len = simple_strtoul(argv[3], NULL, 16);
1238                         /* fall through */
1239                 case 3:
1240                         src = simple_strtoul(argv[1], NULL, 16);
1241                         dst = simple_strtoul(argv[2], NULL, 16);
1242                         break;
1243                 default:
1244                         cmd_usage(cmdtp);
1245                         return 1;
1246         }
1247
1248         return !!gunzip((void *) dst, dst_len, (void *) src, &src_len);
1249 }
1250 #endif /* CONFIG_CMD_UNZIP */
1251
1252
1253 /**************************************************/
1254 U_BOOT_CMD(
1255         md,     3,      1,      do_mem_md,
1256         "memory display",
1257         "[.b, .w, .l] address [# of objects]"
1258 );
1259
1260
1261 U_BOOT_CMD(
1262         mm,     2,      1,      do_mem_mm,
1263         "memory modify (auto-incrementing address)",
1264         "[.b, .w, .l] address"
1265 );
1266
1267
1268 U_BOOT_CMD(
1269         nm,     2,      1,      do_mem_nm,
1270         "memory modify (constant address)",
1271         "[.b, .w, .l] address"
1272 );
1273
1274 U_BOOT_CMD(
1275         mw,     4,      1,      do_mem_mw,
1276         "memory write (fill)",
1277         "[.b, .w, .l] address value [count]"
1278 );
1279
1280 U_BOOT_CMD(
1281         cp,     4,      1,      do_mem_cp,
1282         "memory copy",
1283         "[.b, .w, .l] source target count"
1284 );
1285
1286 U_BOOT_CMD(
1287         cmp,    4,      1,      do_mem_cmp,
1288         "memory compare",
1289         "[.b, .w, .l] addr1 addr2 count"
1290 );
1291
1292 #ifndef CONFIG_CRC32_VERIFY
1293
1294 U_BOOT_CMD(
1295         crc32,  4,      1,      do_mem_crc,
1296         "checksum calculation",
1297         "address count [addr]\n    - compute CRC32 checksum [save at addr]"
1298 );
1299
1300 #else   /* CONFIG_CRC32_VERIFY */
1301
1302 U_BOOT_CMD(
1303         crc32,  5,      1,      do_mem_crc,
1304         "checksum calculation",
1305         "address count [addr]\n    - compute CRC32 checksum [save at addr]\n"
1306         "-v address count crc\n    - verify crc of memory area"
1307 );
1308
1309 #endif  /* CONFIG_CRC32_VERIFY */
1310
1311 U_BOOT_CMD(
1312         base,   2,      1,      do_mem_base,
1313         "print or set address offset",
1314         "\n    - print address offset for memory commands\n"
1315         "base off\n    - set address offset for memory commands to 'off'"
1316 );
1317
1318 U_BOOT_CMD(
1319         loop,   3,      1,      do_mem_loop,
1320         "infinite loop on address range",
1321         "[.b, .w, .l] address number_of_objects"
1322 );
1323
1324 #ifdef CONFIG_LOOPW
1325 U_BOOT_CMD(
1326         loopw,  4,      1,      do_mem_loopw,
1327         "infinite write loop on address range",
1328         "[.b, .w, .l] address number_of_objects data_to_write"
1329 );
1330 #endif /* CONFIG_LOOPW */
1331
1332 U_BOOT_CMD(
1333         mtest,  5,      1,      do_mem_mtest,
1334         "simple RAM read/write test",
1335         "[start [end [pattern [iterations]]]]"
1336 );
1337
1338 #ifdef CONFIG_MX_CYCLIC
1339 U_BOOT_CMD(
1340         mdc,    4,      1,      do_mem_mdc,
1341         "memory display cyclic",
1342         "[.b, .w, .l] address count delay(ms)"
1343 );
1344
1345 U_BOOT_CMD(
1346         mwc,    4,      1,      do_mem_mwc,
1347         "memory write cyclic",
1348         "[.b, .w, .l] address value delay(ms)"
1349 );
1350 #endif /* CONFIG_MX_CYCLIC */
1351
1352 #ifdef CONFIG_CMD_MD5SUM
1353 U_BOOT_CMD(
1354         md5sum, 3,      1,      do_md5sum,
1355         "compute MD5 message digest",
1356         "address count"
1357 );
1358 #endif
1359
1360 #ifdef CONFIG_CMD_SHA1SUM
1361 U_BOOT_CMD(
1362         sha1sum,        3,      1,      do_sha1sum,
1363         "compute SHA1 message digest",
1364         "address count"
1365 );
1366 #endif /* CONFIG_CMD_SHA1 */
1367
1368 #ifdef CONFIG_CMD_UNZIP
1369 U_BOOT_CMD(
1370         unzip,  4,      1,      do_unzip,
1371         "unzip a memory region",
1372         "srcaddr dstaddr [dstsize]"
1373 );
1374 #endif /* CONFIG_CMD_UNZIP */