uboot/tools/updater/cmd_flash.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 * FLASH support
  26 */
  27#include <common.h>
  28#include <command.h>
  29#include <flash.h>
  30
  31#if defined(CONFIG_CMD_FLASH)
  32
  33extern flash_info_t flash_info[];       /* info for FLASH chips */
  34
  35/*
  36 * The user interface starts numbering for Flash banks with 1
  37 * for historical reasons.
  38 */
  39
  40/*
  41 * this routine looks for an abbreviated flash range specification.
  42 * the syntax is B:SF[-SL], where B is the bank number, SF is the first
  43 * sector to erase, and SL is the last sector to erase (defaults to SF).
  44 * bank numbers start at 1 to be consistent with other specs, sector numbers
  45 * start at zero.
  46 *
  47 * returns:     1       - correct spec; *pinfo, *psf and *psl are
  48 *                        set appropriately
  49 *              0       - doesn't look like an abbreviated spec
  50 *              -1      - looks like an abbreviated spec, but got
  51 *                        a parsing error, a number out of range,
  52 *                        or an invalid flash bank.
  53 */
  54static int
  55abbrev_spec(char *str, flash_info_t **pinfo, int *psf, int *psl)
  56{
  57    flash_info_t *fp;
  58    int bank, first, last;
  59    char *p, *ep;
  60
  61    if ((p = strchr(str, ':')) == NULL)
  62        return 0;
  63    *p++ = '\0';
  64
  65    bank = simple_strtoul(str, &ep, 10);
  66    if (ep == str || *ep != '\0' ||
  67      bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS ||
  68      (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
  69        return -1;
  70
  71    str = p;
  72    if ((p = strchr(str, '-')) != NULL)
  73        *p++ = '\0';
  74
  75    first = simple_strtoul(str, &ep, 10);
  76    if (ep == str || *ep != '\0' || first >= fp->sector_count)
  77        return -1;
  78
  79    if (p != NULL) {
  80        last = simple_strtoul(p, &ep, 10);
  81        if (ep == p || *ep != '\0' ||
  82          last < first || last >= fp->sector_count)
  83            return -1;
  84    }
  85    else
  86        last = first;
  87
  88    *pinfo = fp;
  89    *psf = first;
  90    *psl = last;
  91
  92    return 1;
  93}
  94int do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
  95{
  96        ulong bank;
  97
  98        if (argc == 1) {        /* print info for all FLASH banks */
  99                for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 100                        printf ("\nBank # %ld: ", bank+1);
 101
 102                        flash_print_info (&flash_info[bank]);
 103                }
 104                return 0;
 105        }
 106
 107        bank = simple_strtoul(argv[1], NULL, 16);
 108        if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 109                printf ("Only FLASH Banks # 1 ... # %d supported\n",
 110                        CONFIG_SYS_MAX_FLASH_BANKS);
 111                return 1;
 112        }
 113        printf ("\nBank # %ld: ", bank);
 114        flash_print_info (&flash_info[bank-1]);
 115        return 0;
 116}
 117int do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 118{
 119        flash_info_t *info;
 120        ulong bank, addr_first, addr_last;
 121        int n, sect_first, sect_last;
 122        int rcode = 0;
 123
 124        if (argc < 2)
 125                return cmd_usage(cmdtp);
 126
 127        if (strcmp(argv[1], "all") == 0) {
 128                for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 129                        printf ("Erase Flash Bank # %ld ", bank);
 130                        info = &flash_info[bank-1];
 131                        rcode = flash_erase (info, 0, info->sector_count-1);
 132                }
 133                return rcode;
 134        }
 135
 136        if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
 137                if (n < 0) {
 138                        printf("Bad sector specification\n");
 139                        return 1;
 140                }
 141                printf ("Erase Flash Sectors %d-%d in Bank # %d ",
 142                        sect_first, sect_last, (info-flash_info)+1);
 143                rcode = flash_erase(info, sect_first, sect_last);
 144                return rcode;
 145        }
 146
 147        if (argc != 3)
 148                return cmd_usage(cmdtp);
 149
 150        if (strcmp(argv[1], "bank") == 0) {
 151                bank = simple_strtoul(argv[2], NULL, 16);
 152                if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 153                        printf ("Only FLASH Banks # 1 ... # %d supported\n",
 154                                CONFIG_SYS_MAX_FLASH_BANKS);
 155                        return 1;
 156                }
 157                printf ("Erase Flash Bank # %ld ", bank);
 158                info = &flash_info[bank-1];
 159                rcode = flash_erase (info, 0, info->sector_count-1);
 160                return rcode;
 161        }
 162
 163        addr_first = simple_strtoul(argv[1], NULL, 16);
 164        addr_last  = simple_strtoul(argv[2], NULL, 16);
 165
 166        if (addr_first >= addr_last)
 167                return cmd_usage(cmdtp);
 168
 169        printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
 170        rcode = flash_sect_erase(addr_first, addr_last);
 171        return rcode;
 172}
 173
 174int flash_sect_erase (ulong addr_first, ulong addr_last)
 175{
 176        flash_info_t *info;
 177        ulong bank;
 178        int s_first, s_last;
 179        int erased;
 180        int rcode = 0;
 181
 182        erased = 0;
 183
 184        for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
 185                ulong b_end;
 186                int sect;
 187
 188                if (info->flash_id == FLASH_UNKNOWN) {
 189                        continue;
 190                }
 191
 192                b_end = info->start[0] + info->size - 1; /* bank end addr */
 193
 194                s_first = -1;           /* first sector to erase        */
 195                s_last  = -1;           /* last  sector to erase        */
 196
 197                for (sect=0; sect < info->sector_count; ++sect) {
 198                        ulong end;              /* last address in current sect */
 199                        short s_end;
 200
 201                        s_end = info->sector_count - 1;
 202
 203                        end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
 204
 205                        if (addr_first > end)
 206                                continue;
 207                        if (addr_last < info->start[sect])
 208                                continue;
 209
 210                        if (addr_first == info->start[sect]) {
 211                                s_first = sect;
 212                        }
 213                        if (addr_last  == end) {
 214                                s_last  = sect;
 215                        }
 216                }
 217                if (s_first>=0 && s_first<=s_last) {
 218                        erased += s_last - s_first + 1;
 219                        rcode = flash_erase (info, s_first, s_last);
 220                }
 221        }
 222        if (erased) {
 223            /*  printf ("Erased %d sectors\n", erased); */
 224        } else {
 225                printf ("Error: start and/or end address"
 226                        " not on sector boundary\n");
 227                rcode = 1;
 228        }
 229        return rcode;
 230}
 231
 232
 233int do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 234{
 235        flash_info_t *info;
 236        ulong bank, addr_first, addr_last;
 237        int i, p, n, sect_first, sect_last;
 238        int rcode = 0;
 239
 240        if (argc < 3)
 241                return cmd_usage(cmdtp);
 242
 243        if (strcmp(argv[1], "off") == 0)
 244                p = 0;
 245        else if (strcmp(argv[1], "on") == 0)
 246                p = 1;
 247        else
 248                return cmd_usage(cmdtp);
 249
 250        if (strcmp(argv[2], "all") == 0) {
 251                for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 252                        info = &flash_info[bank-1];
 253                        if (info->flash_id == FLASH_UNKNOWN) {
 254                                continue;
 255                        }
 256                        /*printf ("%sProtect Flash Bank # %ld\n", */
 257                        /*      p ? "" : "Un-", bank); */
 258
 259                        for (i=0; i<info->sector_count; ++i) {
 260#if defined(CONFIG_SYS_FLASH_PROTECTION)
 261                                if (flash_real_protect(info, i, p))
 262                                        rcode = 1;
 263                                putc ('.');
 264#else
 265                                info->protect[i] = p;
 266#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 267                        }
 268                }
 269
 270#if defined(CONFIG_SYS_FLASH_PROTECTION)
 271                if (!rcode) puts (" done\n");
 272#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 273
 274                return rcode;
 275        }
 276
 277        if ((n = abbrev_spec(argv[2], &info, &sect_first, &sect_last)) != 0) {
 278                if (n < 0) {
 279                        printf("Bad sector specification\n");
 280                        return 1;
 281                }
 282                /*printf("%sProtect Flash Sectors %d-%d in Bank # %d\n", */
 283                /*      p ? "" : "Un-", sect_first, sect_last, */
 284                /*      (info-flash_info)+1); */
 285                for (i = sect_first; i <= sect_last; i++) {
 286#if defined(CONFIG_SYS_FLASH_PROTECTION)
 287                        if (flash_real_protect(info, i, p))
 288                                rcode =  1;
 289                        putc ('.');
 290#else
 291                        info->protect[i] = p;
 292#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 293                }
 294
 295#if defined(CONFIG_SYS_FLASH_PROTECTION)
 296                if (!rcode) puts (" done\n");
 297#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 298
 299                return rcode;
 300        }
 301
 302        if (argc != 4)
 303                return cmd_usage(cmdtp);
 304
 305        if (strcmp(argv[2], "bank") == 0) {
 306                bank = simple_strtoul(argv[3], NULL, 16);
 307                if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 308                        printf ("Only FLASH Banks # 1 ... # %d supported\n",
 309                                CONFIG_SYS_MAX_FLASH_BANKS);
 310                        return 1;
 311                }
 312                printf ("%sProtect Flash Bank # %ld\n",
 313                        p ? "" : "Un-", bank);
 314                info = &flash_info[bank-1];
 315
 316                if (info->flash_id == FLASH_UNKNOWN) {
 317                        printf ("missing or unknown FLASH type\n");
 318                        return 1;
 319                }
 320                for (i=0; i<info->sector_count; ++i) {
 321#if defined(CONFIG_SYS_FLASH_PROTECTION)
 322                        if (flash_real_protect(info, i, p))
 323                                rcode =  1;
 324                        putc ('.');
 325#else
 326                        info->protect[i] = p;
 327#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 328                }
 329
 330#if defined(CONFIG_SYS_FLASH_PROTECTION)
 331                if (!rcode)
 332                        puts(" done\n");
 333#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 334
 335                return rcode;
 336        }
 337
 338        addr_first = simple_strtoul(argv[2], NULL, 16);
 339        addr_last  = simple_strtoul(argv[3], NULL, 16);
 340
 341        if (addr_first >= addr_last)
 342                return cmd_usage(cmdtp);
 343
 344        return flash_sect_protect (p, addr_first, addr_last);
 345}
 346int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
 347{
 348        flash_info_t *info;
 349        ulong bank;
 350        int s_first, s_last;
 351        int protected, i;
 352        int rcode = 0;
 353
 354        protected = 0;
 355
 356        for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
 357                ulong b_end;
 358                int sect;
 359
 360                if (info->flash_id == FLASH_UNKNOWN) {
 361                        continue;
 362                }
 363
 364                b_end = info->start[0] + info->size - 1; /* bank end addr */
 365
 366                s_first = -1;           /* first sector to erase        */
 367                s_last  = -1;           /* last  sector to erase        */
 368
 369                for (sect=0; sect < info->sector_count; ++sect) {
 370                        ulong end;              /* last address in current sect */
 371                        short s_end;
 372
 373                        s_end = info->sector_count - 1;
 374
 375                        end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
 376
 377                        if (addr_first > end)
 378                                continue;
 379                        if (addr_last < info->start[sect])
 380                                continue;
 381
 382                        if (addr_first == info->start[sect]) {
 383                                s_first = sect;
 384                        }
 385                        if (addr_last  == end) {
 386                                s_last  = sect;
 387                        }
 388                }
 389                if (s_first>=0 && s_first<=s_last) {
 390                        protected += s_last - s_first + 1;
 391                        for (i=s_first; i<=s_last; ++i) {
 392#if defined(CONFIG_SYS_FLASH_PROTECTION)
 393                                if (flash_real_protect(info, i, p))
 394                                        rcode = 1;
 395                                putc ('.');
 396#else
 397                                info->protect[i] = p;
 398#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 399                        }
 400                }
 401#if defined(CONFIG_SYS_FLASH_PROTECTION)
 402                if (!rcode) putc ('\n');
 403#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 404
 405        }
 406        if (protected) {
 407            /*  printf ("%sProtected %d sectors\n", */
 408            /*  p ? "" : "Un-", protected); */
 409        } else {
 410            printf ("Error: start and/or end address"
 411                        " not on sector boundary\n");
 412                rcode = 1;
 413        }
 414        return rcode;
 415}
 416
 417#endif
 418