~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/common/cmd_flash.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

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