uboot/cmd/flash.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2000
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 */
   6
   7/*
   8 * FLASH support
   9 */
  10#include <common.h>
  11#include <command.h>
  12
  13#if defined(CONFIG_CMD_MTDPARTS)
  14#include <jffs2/jffs2.h>
  15
  16/* partition handling routines */
  17int mtdparts_init(void);
  18int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
  19int find_dev_and_part(const char *id, struct mtd_device **dev,
  20                u8 *part_num, struct part_info **part);
  21#endif
  22
  23#ifdef CONFIG_MTD_NOR_FLASH
  24#include <flash.h>
  25#include <mtd/cfi_flash.h>
  26extern flash_info_t flash_info[];       /* info for FLASH chips */
  27
  28/*
  29 * The user interface starts numbering for Flash banks with 1
  30 * for historical reasons.
  31 */
  32
  33/*
  34 * this routine looks for an abbreviated flash range specification.
  35 * the syntax is B:SF[-SL], where B is the bank number, SF is the first
  36 * sector to erase, and SL is the last sector to erase (defaults to SF).
  37 * bank numbers start at 1 to be consistent with other specs, sector numbers
  38 * start at zero.
  39 *
  40 * returns:     1       - correct spec; *pinfo, *psf and *psl are
  41 *                        set appropriately
  42 *              0       - doesn't look like an abbreviated spec
  43 *              -1      - looks like an abbreviated spec, but got
  44 *                        a parsing error, a number out of range,
  45 *                        or an invalid flash bank.
  46 */
  47static int
  48abbrev_spec (char *str, flash_info_t ** pinfo, int *psf, int *psl)
  49{
  50        flash_info_t *fp;
  51        int bank, first, last;
  52        char *p, *ep;
  53
  54        if ((p = strchr (str, ':')) == NULL)
  55                return 0;
  56        *p++ = '\0';
  57
  58        bank = simple_strtoul (str, &ep, 10);
  59        if (ep == str || *ep != '\0' ||
  60                bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS ||
  61                (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
  62                return -1;
  63
  64        str = p;
  65        if ((p = strchr (str, '-')) != NULL)
  66                *p++ = '\0';
  67
  68        first = simple_strtoul (str, &ep, 10);
  69        if (ep == str || *ep != '\0' || first >= fp->sector_count)
  70                return -1;
  71
  72        if (p != NULL) {
  73                last = simple_strtoul (p, &ep, 10);
  74                if (ep == p || *ep != '\0' ||
  75                        last < first || last >= fp->sector_count)
  76                        return -1;
  77        } else {
  78                last = first;
  79        }
  80
  81        *pinfo = fp;
  82        *psf = first;
  83        *psl = last;
  84
  85        return 1;
  86}
  87
  88/*
  89 * Take *addr in Flash and adjust it to fall on the end of its sector
  90 */
  91int flash_sect_roundb (ulong *addr)
  92{
  93        flash_info_t *info;
  94        ulong bank, sector_end_addr;
  95        char found;
  96        int i;
  97
  98        /* find the end addr of the sector where the *addr is */
  99        found = 0;
 100        for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS && !found; ++bank) {
 101                info = &flash_info[bank];
 102                for (i = 0; i < info->sector_count && !found; ++i) {
 103                        /* get the end address of the sector */
 104                        if (i == info->sector_count - 1) {
 105                                sector_end_addr = info->start[0] +
 106                                                                info->size - 1;
 107                        } else {
 108                                sector_end_addr = info->start[i+1] - 1;
 109                        }
 110
 111                        if (*addr <= sector_end_addr &&
 112                                                *addr >= info->start[i]) {
 113                                found = 1;
 114                                /* adjust *addr if necessary */
 115                                if (*addr < sector_end_addr)
 116                                        *addr = sector_end_addr;
 117                        } /* sector */
 118                } /* bank */
 119        }
 120        if (!found) {
 121                /* error, address not in flash */
 122                printf("Error: end address (0x%08lx) not in flash!\n", *addr);
 123                return 1;
 124        }
 125
 126        return 0;
 127}
 128
 129/*
 130 * This function computes the start and end addresses for both
 131 * erase and protect commands. The range of the addresses on which
 132 * either of the commands is to operate can be given in two forms:
 133 * 1. <cmd> start end - operate on <'start',  'end')
 134 * 2. <cmd> start +length - operate on <'start', start + length)
 135 * If the second form is used and the end address doesn't fall on the
 136 * sector boundary, than it will be adjusted to the next sector boundary.
 137 * If it isn't in the flash, the function will fail (return -1).
 138 * Input:
 139 *    arg1, arg2: address specification (i.e. both command arguments)
 140 * Output:
 141 *    addr_first, addr_last: computed address range
 142 * Return:
 143 *    1: success
 144 *   -1: failure (bad format, bad address).
 145*/
 146static int
 147addr_spec(char *arg1, char *arg2, ulong *addr_first, ulong *addr_last)
 148{
 149        char *ep;
 150        char len_used; /* indicates if the "start +length" form used */
 151
 152        *addr_first = simple_strtoul(arg1, &ep, 16);
 153        if (ep == arg1 || *ep != '\0')
 154                return -1;
 155
 156        len_used = 0;
 157        if (arg2 && *arg2 == '+'){
 158                len_used = 1;
 159                ++arg2;
 160        }
 161
 162        *addr_last = simple_strtoul(arg2, &ep, 16);
 163        if (ep == arg2 || *ep != '\0')
 164                return -1;
 165
 166        if (len_used){
 167                /*
 168                 * *addr_last has the length, compute correct *addr_last
 169                 * XXX watch out for the integer overflow! Right now it is
 170                 * checked for in both the callers.
 171                 */
 172                *addr_last = *addr_first + *addr_last - 1;
 173
 174                /*
 175                 * It may happen that *addr_last doesn't fall on the sector
 176                 * boundary. We want to round such an address to the next
 177                 * sector boundary, so that the commands don't fail later on.
 178                 */
 179
 180                if (flash_sect_roundb(addr_last) > 0)
 181                        return -1;
 182        } /* "start +length" from used */
 183
 184        return 1;
 185}
 186
 187static int
 188flash_fill_sect_ranges (ulong addr_first, ulong addr_last,
 189                        int *s_first, int *s_last,
 190                        int *s_count )
 191{
 192        flash_info_t *info;
 193        ulong bank;
 194        int rcode = 0;
 195
 196        *s_count = 0;
 197
 198        for (bank=0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 199                s_first[bank] = -1;     /* first sector to erase        */
 200                s_last [bank] = -1;     /* last  sector to erase        */
 201        }
 202
 203        for (bank=0,info = &flash_info[0];
 204             (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (addr_first <= addr_last);
 205             ++bank, ++info) {
 206                ulong b_end;
 207                int sect;
 208                short s_end;
 209
 210                if (info->flash_id == FLASH_UNKNOWN) {
 211                        continue;
 212                }
 213
 214                b_end = info->start[0] + info->size - 1;        /* bank end addr */
 215                s_end = info->sector_count - 1;                 /* last sector   */
 216
 217
 218                for (sect=0; sect < info->sector_count; ++sect) {
 219                        ulong end;      /* last address in current sect */
 220
 221                        end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
 222
 223                        if (addr_first > end)
 224                                continue;
 225                        if (addr_last < info->start[sect])
 226                                continue;
 227
 228                        if (addr_first == info->start[sect]) {
 229                                s_first[bank] = sect;
 230                        }
 231                        if (addr_last  == end) {
 232                                s_last[bank]  = sect;
 233                        }
 234                }
 235                if (s_first[bank] >= 0) {
 236                        if (s_last[bank] < 0) {
 237                                if (addr_last > b_end) {
 238                                        s_last[bank] = s_end;
 239                                } else {
 240                                        puts ("Error: end address"
 241                                                " not on sector boundary\n");
 242                                        rcode = 1;
 243                                        break;
 244                                }
 245                        }
 246                        if (s_last[bank] < s_first[bank]) {
 247                                puts ("Error: end sector"
 248                                        " precedes start sector\n");
 249                                rcode = 1;
 250                                break;
 251                        }
 252                        sect = s_last[bank];
 253                        addr_first = (sect == s_end) ? b_end + 1: info->start[sect + 1];
 254                        (*s_count) += s_last[bank] - s_first[bank] + 1;
 255                } else if (addr_first >= info->start[0] && addr_first < b_end) {
 256                        puts ("Error: start address not on sector boundary\n");
 257                        rcode = 1;
 258                        break;
 259                } else if (s_last[bank] >= 0) {
 260                        puts ("Error: cannot span across banks when they are"
 261                               " mapped in reverse order\n");
 262                        rcode = 1;
 263                        break;
 264                }
 265        }
 266
 267        return rcode;
 268}
 269#endif /* CONFIG_MTD_NOR_FLASH */
 270
 271static int do_flinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 272{
 273#ifdef CONFIG_MTD_NOR_FLASH
 274        ulong bank;
 275#endif
 276
 277#ifdef CONFIG_MTD_NOR_FLASH
 278        if (argc == 1) {        /* print info for all FLASH banks */
 279                for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 280                        printf ("\nBank # %ld: ", bank+1);
 281
 282                        flash_print_info (&flash_info[bank]);
 283                }
 284                return 0;
 285        }
 286
 287        bank = simple_strtoul(argv[1], NULL, 16);
 288        if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 289                printf ("Only FLASH Banks # 1 ... # %d supported\n",
 290                        CONFIG_SYS_MAX_FLASH_BANKS);
 291                return 1;
 292        }
 293        printf ("\nBank # %ld: ", bank);
 294        flash_print_info (&flash_info[bank-1]);
 295#endif /* CONFIG_MTD_NOR_FLASH */
 296        return 0;
 297}
 298
 299static int do_flerase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 300{
 301#ifdef CONFIG_MTD_NOR_FLASH
 302        flash_info_t *info = NULL;
 303        ulong bank, addr_first, addr_last;
 304        int n, sect_first = 0, sect_last = 0;
 305#if defined(CONFIG_CMD_MTDPARTS)
 306        struct mtd_device *dev;
 307        struct part_info *part;
 308        u8 dev_type, dev_num, pnum;
 309#endif
 310        int rcode = 0;
 311
 312        if (argc < 2)
 313                return CMD_RET_USAGE;
 314
 315        if (strcmp(argv[1], "all") == 0) {
 316                for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 317                        printf ("Erase Flash Bank # %ld ", bank);
 318                        info = &flash_info[bank-1];
 319                        rcode = flash_erase (info, 0, info->sector_count-1);
 320                }
 321                return rcode;
 322        }
 323
 324        if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
 325                if (n < 0) {
 326                        puts ("Bad sector specification\n");
 327                        return 1;
 328                }
 329                printf ("Erase Flash Sectors %d-%d in Bank # %zu ",
 330                        sect_first, sect_last, (info-flash_info)+1);
 331                rcode = flash_erase(info, sect_first, sect_last);
 332                return rcode;
 333        }
 334
 335#if defined(CONFIG_CMD_MTDPARTS)
 336        /* erase <part-id> - erase partition */
 337        if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
 338                mtdparts_init();
 339                if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
 340                        if (dev->id->type == MTD_DEV_TYPE_NOR) {
 341                                bank = dev->id->num;
 342                                info = &flash_info[bank];
 343                                addr_first = part->offset + info->start[0];
 344                                addr_last = addr_first + part->size - 1;
 345
 346                                printf ("Erase Flash Partition %s, "
 347                                                "bank %ld, 0x%08lx - 0x%08lx ",
 348                                                argv[1], bank, addr_first,
 349                                                addr_last);
 350
 351                                rcode = flash_sect_erase(addr_first, addr_last);
 352                                return rcode;
 353                        }
 354
 355                        printf("cannot erase, not a NOR device\n");
 356                        return 1;
 357                }
 358        }
 359#endif
 360
 361        if (argc != 3)
 362                return CMD_RET_USAGE;
 363
 364        if (strcmp(argv[1], "bank") == 0) {
 365                bank = simple_strtoul(argv[2], NULL, 16);
 366                if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 367                        printf ("Only FLASH Banks # 1 ... # %d supported\n",
 368                                CONFIG_SYS_MAX_FLASH_BANKS);
 369                        return 1;
 370                }
 371                printf ("Erase Flash Bank # %ld ", bank);
 372                info = &flash_info[bank-1];
 373                rcode = flash_erase (info, 0, info->sector_count-1);
 374                return rcode;
 375        }
 376
 377        if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
 378                printf ("Bad address format\n");
 379                return 1;
 380        }
 381
 382        if (addr_first >= addr_last)
 383                return CMD_RET_USAGE;
 384
 385        rcode = flash_sect_erase(addr_first, addr_last);
 386        return rcode;
 387#else
 388        return 0;
 389#endif /* CONFIG_MTD_NOR_FLASH */
 390}
 391
 392#ifdef CONFIG_MTD_NOR_FLASH
 393int flash_sect_erase (ulong addr_first, ulong addr_last)
 394{
 395        flash_info_t *info;
 396        ulong bank;
 397        int s_first[CONFIG_SYS_MAX_FLASH_BANKS], s_last[CONFIG_SYS_MAX_FLASH_BANKS];
 398        int erased = 0;
 399        int planned;
 400        int rcode = 0;
 401
 402        rcode = flash_fill_sect_ranges (addr_first, addr_last,
 403                                        s_first, s_last, &planned );
 404
 405        if (planned && (rcode == 0)) {
 406                for (bank=0,info = &flash_info[0];
 407                     (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (rcode == 0);
 408                     ++bank, ++info) {
 409                        if (s_first[bank]>=0) {
 410                                erased += s_last[bank] - s_first[bank] + 1;
 411                                debug ("Erase Flash from 0x%08lx to 0x%08lx "
 412                                        "in Bank # %ld ",
 413                                        info->start[s_first[bank]],
 414                                        (s_last[bank] == info->sector_count) ?
 415                                                info->start[0] + info->size - 1:
 416                                                info->start[s_last[bank]+1] - 1,
 417                                        bank+1);
 418                                rcode = flash_erase (info, s_first[bank], s_last[bank]);
 419                        }
 420                }
 421                if (rcode == 0)
 422                        printf("Erased %d sectors\n", erased);
 423        } else if (rcode == 0) {
 424                puts ("Error: start and/or end address"
 425                        " not on sector boundary\n");
 426                rcode = 1;
 427        }
 428        return rcode;
 429}
 430#endif /* CONFIG_MTD_NOR_FLASH */
 431
 432static int do_protect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 433{
 434        int rcode = 0;
 435#ifdef CONFIG_MTD_NOR_FLASH
 436        flash_info_t *info = NULL;
 437        ulong bank;
 438        int i, n, sect_first = 0, sect_last = 0;
 439#if defined(CONFIG_CMD_MTDPARTS)
 440        struct mtd_device *dev;
 441        struct part_info *part;
 442        u8 dev_type, dev_num, pnum;
 443#endif
 444#endif /* CONFIG_MTD_NOR_FLASH */
 445#if defined(CONFIG_MTD_NOR_FLASH)
 446        int p;
 447        ulong addr_first, addr_last;
 448#endif
 449
 450        if (argc < 3)
 451                return CMD_RET_USAGE;
 452
 453#if defined(CONFIG_MTD_NOR_FLASH)
 454        if (strcmp(argv[1], "off") == 0)
 455                p = 0;
 456        else if (strcmp(argv[1], "on") == 0)
 457                p = 1;
 458        else
 459                return CMD_RET_USAGE;
 460#endif
 461
 462#ifdef CONFIG_MTD_NOR_FLASH
 463        if (strcmp(argv[2], "all") == 0) {
 464                for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 465                        info = &flash_info[bank-1];
 466                        if (info->flash_id == FLASH_UNKNOWN) {
 467                                continue;
 468                        }
 469                        printf ("%sProtect Flash Bank # %ld\n",
 470                                p ? "" : "Un-", bank);
 471
 472                        for (i=0; i<info->sector_count; ++i) {
 473#if defined(CONFIG_SYS_FLASH_PROTECTION)
 474                                if (flash_real_protect(info, i, p))
 475                                        rcode = 1;
 476                                putc ('.');
 477#else
 478                                info->protect[i] = p;
 479#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 480                        }
 481#if defined(CONFIG_SYS_FLASH_PROTECTION)
 482                        if (!rcode) puts (" done\n");
 483#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 484                }
 485                return rcode;
 486        }
 487
 488        if ((n = abbrev_spec(argv[2], &info, &sect_first, &sect_last)) != 0) {
 489                if (n < 0) {
 490                        puts ("Bad sector specification\n");
 491                        return 1;
 492                }
 493                printf("%sProtect Flash Sectors %d-%d in Bank # %zu\n",
 494                        p ? "" : "Un-", sect_first, sect_last,
 495                        (info-flash_info)+1);
 496                for (i = sect_first; i <= sect_last; i++) {
 497#if defined(CONFIG_SYS_FLASH_PROTECTION)
 498                        if (flash_real_protect(info, i, p))
 499                                rcode =  1;
 500                        putc ('.');
 501#else
 502                        info->protect[i] = p;
 503#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 504                }
 505
 506#if defined(CONFIG_SYS_FLASH_PROTECTION)
 507                if (!rcode) puts (" done\n");
 508#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 509
 510                return rcode;
 511        }
 512
 513#if defined(CONFIG_CMD_MTDPARTS)
 514        /* protect on/off <part-id> */
 515        if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
 516                mtdparts_init();
 517                if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) {
 518                        if (dev->id->type == MTD_DEV_TYPE_NOR) {
 519                                bank = dev->id->num;
 520                                info = &flash_info[bank];
 521                                addr_first = part->offset + info->start[0];
 522                                addr_last = addr_first + part->size - 1;
 523
 524                                printf ("%sProtect Flash Partition %s, "
 525                                                "bank %ld, 0x%08lx - 0x%08lx\n",
 526                                                p ? "" : "Un", argv[1],
 527                                                bank, addr_first, addr_last);
 528
 529                                rcode = flash_sect_protect (p, addr_first, addr_last);
 530                                return rcode;
 531                        }
 532
 533                        printf("cannot %sprotect, not a NOR device\n",
 534                                        p ? "" : "un");
 535                        return 1;
 536                }
 537        }
 538#endif
 539
 540        if (argc != 4)
 541                return CMD_RET_USAGE;
 542
 543        if (strcmp(argv[2], "bank") == 0) {
 544                bank = simple_strtoul(argv[3], NULL, 16);
 545                if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 546                        printf ("Only FLASH Banks # 1 ... # %d supported\n",
 547                                CONFIG_SYS_MAX_FLASH_BANKS);
 548                        return 1;
 549                }
 550                printf ("%sProtect Flash Bank # %ld\n",
 551                        p ? "" : "Un-", bank);
 552                info = &flash_info[bank-1];
 553
 554                if (info->flash_id == FLASH_UNKNOWN) {
 555                        puts ("missing or unknown FLASH type\n");
 556                        return 1;
 557                }
 558                for (i=0; i<info->sector_count; ++i) {
 559#if defined(CONFIG_SYS_FLASH_PROTECTION)
 560                        if (flash_real_protect(info, i, p))
 561                                rcode =  1;
 562                        putc ('.');
 563#else
 564                        info->protect[i] = p;
 565#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 566                }
 567
 568#if defined(CONFIG_SYS_FLASH_PROTECTION)
 569                if (!rcode) puts (" done\n");
 570#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 571
 572                return rcode;
 573        }
 574
 575        if (addr_spec(argv[2], argv[3], &addr_first, &addr_last) < 0){
 576                printf("Bad address format\n");
 577                return 1;
 578        }
 579
 580        if (addr_first >= addr_last)
 581                return CMD_RET_USAGE;
 582
 583        rcode = flash_sect_protect (p, addr_first, addr_last);
 584#endif /* CONFIG_MTD_NOR_FLASH */
 585        return rcode;
 586}
 587
 588#ifdef CONFIG_MTD_NOR_FLASH
 589int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
 590{
 591        flash_info_t *info;
 592        ulong bank;
 593        int s_first[CONFIG_SYS_MAX_FLASH_BANKS], s_last[CONFIG_SYS_MAX_FLASH_BANKS];
 594        int protected, i;
 595        int planned;
 596        int rcode;
 597
 598        rcode = flash_fill_sect_ranges( addr_first, addr_last, s_first, s_last, &planned );
 599
 600        protected = 0;
 601
 602        if (planned && (rcode == 0)) {
 603                for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
 604                        if (info->flash_id == FLASH_UNKNOWN) {
 605                                continue;
 606                        }
 607
 608                        if (s_first[bank]>=0 && s_first[bank]<=s_last[bank]) {
 609                                debug ("%sProtecting sectors %d..%d in bank %ld\n",
 610                                        p ? "" : "Un-",
 611                                        s_first[bank], s_last[bank], bank+1);
 612                                protected += s_last[bank] - s_first[bank] + 1;
 613                                for (i=s_first[bank]; i<=s_last[bank]; ++i) {
 614#if defined(CONFIG_SYS_FLASH_PROTECTION)
 615                                        if (flash_real_protect(info, i, p))
 616                                                rcode = 1;
 617                                        putc ('.');
 618#else
 619                                        info->protect[i] = p;
 620#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 621                                }
 622                        }
 623                }
 624#if defined(CONFIG_SYS_FLASH_PROTECTION)
 625                puts (" done\n");
 626#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 627
 628                printf ("%sProtected %d sectors\n",
 629                        p ? "" : "Un-", protected);
 630        } else if (rcode == 0) {
 631                puts ("Error: start and/or end address"
 632                        " not on sector boundary\n");
 633                rcode = 1;
 634        }
 635        return rcode;
 636}
 637#endif /* CONFIG_MTD_NOR_FLASH */
 638
 639
 640/**************************************************/
 641#if defined(CONFIG_CMD_MTDPARTS)
 642# define TMP_ERASE      "erase <part-id>\n    - erase partition\n"
 643# define TMP_PROT_ON    "protect on <part-id>\n    - protect partition\n"
 644# define TMP_PROT_OFF   "protect off <part-id>\n    - make partition writable\n"
 645#else
 646# define TMP_ERASE      /* empty */
 647# define TMP_PROT_ON    /* empty */
 648# define TMP_PROT_OFF   /* empty */
 649#endif
 650
 651U_BOOT_CMD(
 652        flinfo,    2,    1,    do_flinfo,
 653        "print FLASH memory information",
 654        "\n    - print information for all FLASH memory banks\n"
 655        "flinfo N\n    - print information for FLASH memory bank # N"
 656);
 657
 658U_BOOT_CMD(
 659        erase,   3,   0,  do_flerase,
 660        "erase FLASH memory",
 661        "start end\n"
 662        "    - erase FLASH from addr 'start' to addr 'end'\n"
 663        "erase start +len\n"
 664        "    - erase FLASH from addr 'start' to the end of sect "
 665        "w/addr 'start'+'len'-1\n"
 666        "erase N:SF[-SL]\n    - erase sectors SF-SL in FLASH bank # N\n"
 667        "erase bank N\n    - erase FLASH bank # N\n"
 668        TMP_ERASE
 669        "erase all\n    - erase all FLASH banks"
 670);
 671
 672U_BOOT_CMD(
 673        protect,  4,  0,   do_protect,
 674        "enable or disable FLASH write protection",
 675        "on  start end\n"
 676        "    - protect FLASH from addr 'start' to addr 'end'\n"
 677        "protect on start +len\n"
 678        "    - protect FLASH from addr 'start' to end of sect "
 679        "w/addr 'start'+'len'-1\n"
 680        "protect on  N:SF[-SL]\n"
 681        "    - protect sectors SF-SL in FLASH bank # N\n"
 682        "protect on  bank N\n    - protect FLASH bank # N\n"
 683        TMP_PROT_ON
 684        "protect on  all\n    - protect all FLASH banks\n"
 685        "protect off start end\n"
 686        "    - make FLASH from addr 'start' to addr 'end' writable\n"
 687        "protect off start +len\n"
 688        "    - make FLASH from addr 'start' to end of sect "
 689        "w/addr 'start'+'len'-1 wrtable\n"
 690        "protect off N:SF[-SL]\n"
 691        "    - make sectors SF-SL writable in FLASH bank # N\n"
 692        "protect off bank N\n    - make FLASH bank # N writable\n"
 693        TMP_PROT_OFF
 694        "protect off all\n    - make all FLASH banks writable"
 695);
 696
 697#undef  TMP_ERASE
 698#undef  TMP_PROT_ON
 699#undef  TMP_PROT_OFF
 700