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