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