87c8cede7a9f54ead1d81011934ab5cd0d705668
[fw/openocd] / src / flash / nor / tcl.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de>              *
3  *   Copyright (C) 2007,2008 Ã˜yvind Harboe <oyvind.harboe@zylin.com>       *
4  *   Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk>           *
5  *   Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>             *
6  *   Copyright (C) 2017-2018 Tomas Vanek <vanekt@fbl.cz>                   *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (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, see <http://www.gnu.org/licenses/>. *
20  ***************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include "imp.h"
25 #include <helper/time_support.h>
26 #include <target/image.h>
27
28 /**
29  * @file
30  * Implements Tcl commands used to access NOR flash facilities.
31  */
32
33 static COMMAND_HELPER(flash_command_get_bank_maybe_probe, unsigned name_index,
34                struct flash_bank **bank, bool do_probe)
35 {
36         const char *name = CMD_ARGV[name_index];
37         int retval;
38         if (do_probe) {
39                 retval = get_flash_bank_by_name(name, bank);
40         } else {
41                 *bank  = get_flash_bank_by_name_noprobe(name);
42                 retval = ERROR_OK;
43         }
44
45         if (retval != ERROR_OK)
46                 return retval;
47         if (*bank)
48                 return ERROR_OK;
49
50         unsigned bank_num;
51         COMMAND_PARSE_NUMBER(uint, name, bank_num);
52
53         if (do_probe) {
54                 return get_flash_bank_by_num(bank_num, bank);
55         } else {
56                 *bank  = get_flash_bank_by_num_noprobe(bank_num);
57                 retval = (bank) ? ERROR_OK : ERROR_FAIL;
58                 return retval;
59         }
60 }
61
62 COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
63         struct flash_bank **bank)
64 {
65         return CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe,
66                                     name_index, bank, true);
67 }
68
69 COMMAND_HANDLER(handle_flash_info_command)
70 {
71         struct flash_bank *p;
72         int j = 0;
73         int retval;
74         bool show_sectors = false;
75         bool prot_block_available;
76
77         if (CMD_ARGC < 1 || CMD_ARGC > 2)
78                 return ERROR_COMMAND_SYNTAX_ERROR;
79
80         if (CMD_ARGC == 2) {
81                 if (strcmp("sectors", CMD_ARGV[1]) == 0)
82                         show_sectors = true;
83                 else
84                         return ERROR_COMMAND_SYNTAX_ERROR;
85         }
86
87         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
88         if (retval != ERROR_OK)
89                 return retval;
90
91         if (p != NULL) {
92                 char buf[1024];
93                 int num_blocks;
94                 struct flash_sector *block_array;
95
96                 /* attempt auto probe */
97                 retval = p->driver->auto_probe(p);
98                 if (retval != ERROR_OK)
99                         return retval;
100
101                 /* If the driver does not implement protection, we show the default
102                  * state of is_protected array - usually protection state unknown */
103                 if (p->driver->protect_check == NULL) {
104                         retval = ERROR_FLASH_OPER_UNSUPPORTED;
105                 } else {
106                         /* We must query the hardware to avoid printing stale information! */
107                         retval = p->driver->protect_check(p);
108                         if (retval != ERROR_OK && retval != ERROR_FLASH_OPER_UNSUPPORTED)
109                                 return retval;
110                 }
111                 if (retval == ERROR_FLASH_OPER_UNSUPPORTED)
112                         LOG_INFO("Flash protection check is not implemented.");
113
114                 command_print(CMD,
115                         "#%u : %s at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32
116                         ", buswidth %u, chipwidth %u",
117                         p->bank_number,
118                         p->driver->name,
119                         p->base,
120                         p->size,
121                         p->bus_width,
122                         p->chip_width);
123
124                 prot_block_available = p->num_prot_blocks && p->prot_blocks;
125                 if (!show_sectors && prot_block_available) {
126                         block_array = p->prot_blocks;
127                         num_blocks = p->num_prot_blocks;
128                 } else {
129                         block_array = p->sectors;
130                         num_blocks = p->num_sectors;
131                 }
132
133                 for (j = 0; j < num_blocks; j++) {
134                         char *protect_state = "";
135
136                         if (block_array[j].is_protected == 0)
137                                 protect_state = "not protected";
138                         else if (block_array[j].is_protected == 1)
139                                 protect_state = "protected";
140                         else if (!show_sectors || !prot_block_available)
141                                 protect_state = "protection state unknown";
142
143                         command_print(CMD,
144                                 "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIu32 "kB) %s",
145                                 j,
146                                 block_array[j].offset,
147                                 block_array[j].size,
148                                 block_array[j].size >> 10,
149                                 protect_state);
150                 }
151
152                 if (p->driver->info != NULL) {
153                         retval = p->driver->info(p, buf, sizeof(buf));
154                         if (retval == ERROR_OK)
155                                 command_print(CMD, "%s", buf);
156                         else
157                                 LOG_ERROR("error retrieving flash info");
158                 }
159         }
160
161         return retval;
162 }
163
164 COMMAND_HANDLER(handle_flash_probe_command)
165 {
166         struct flash_bank *p;
167         int retval;
168
169         if (CMD_ARGC != 1)
170                 return ERROR_COMMAND_SYNTAX_ERROR;
171
172         retval = CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, 0, &p, false);
173         if (retval != ERROR_OK)
174                 return retval;
175
176         if (p) {
177                 retval = p->driver->probe(p);
178                 if (retval == ERROR_OK)
179                         command_print(CMD,
180                                 "flash '%s' found at " TARGET_ADDR_FMT,
181                                 p->driver->name,
182                                 p->base);
183         } else {
184                 command_print(CMD, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
185                 retval = ERROR_FAIL;
186         }
187
188         return retval;
189 }
190
191 COMMAND_HANDLER(handle_flash_erase_check_command)
192 {
193         bool blank = true;
194         if (CMD_ARGC != 1)
195                 return ERROR_COMMAND_SYNTAX_ERROR;
196
197         struct flash_bank *p;
198         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
199         if (ERROR_OK != retval)
200                 return retval;
201
202         retval = p->driver->erase_check(p);
203         if (retval == ERROR_OK)
204                 command_print(CMD, "successfully checked erase state");
205         else {
206                 command_print(CMD,
207                         "unknown error when checking erase state of flash bank #%s at "
208                         TARGET_ADDR_FMT,
209                         CMD_ARGV[0],
210                         p->base);
211         }
212
213         for (unsigned int j = 0; j < p->num_sectors; j++) {
214                 char *erase_state;
215
216                 if (p->sectors[j].is_erased == 0)
217                         erase_state = "not erased";
218                 else if (p->sectors[j].is_erased == 1)
219                         continue;
220                 else
221                         erase_state = "erase state unknown";
222
223                 blank = false;
224                 command_print(CMD,
225                         "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIu32 "kB) %s",
226                         j,
227                         p->sectors[j].offset,
228                         p->sectors[j].size,
229                         p->sectors[j].size >> 10,
230                         erase_state);
231         }
232
233         if (blank)
234                 command_print(CMD, "\tBank is erased");
235         return retval;
236 }
237
238 COMMAND_HANDLER(handle_flash_erase_address_command)
239 {
240         struct flash_bank *p;
241         int retval = ERROR_OK;
242         target_addr_t address;
243         uint32_t length;
244         bool do_pad = false;
245         bool do_unlock = false;
246         struct target *target = get_current_target(CMD_CTX);
247
248         while (CMD_ARGC >= 3) {
249                 /* Optionally pad out the address range to block/sector
250                  * boundaries.  We can't know if there's data in that part
251                  * of the flash; only do padding if we're told to.
252                  */
253                 if (strcmp("pad", CMD_ARGV[0]) == 0)
254                         do_pad = true;
255                 else if (strcmp("unlock", CMD_ARGV[0]) == 0)
256                         do_unlock = true;
257                 else
258                         return ERROR_COMMAND_SYNTAX_ERROR;
259                 CMD_ARGC--;
260                 CMD_ARGV++;
261         }
262         if (CMD_ARGC != 2)
263                 return ERROR_COMMAND_SYNTAX_ERROR;
264
265         COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
266         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
267
268         if (length <= 0) {
269                 command_print(CMD, "Length must be >0");
270                 return ERROR_COMMAND_SYNTAX_ERROR;
271         }
272
273         retval = get_flash_bank_by_addr(target, address, true, &p);
274         if (retval != ERROR_OK)
275                 return retval;
276
277         /* We can't know if we did a resume + halt, in which case we no longer know the erased state
278          **/
279         flash_set_dirty();
280
281         struct duration bench;
282         duration_start(&bench);
283
284         if (do_unlock)
285                 retval = flash_unlock_address_range(target, address, length);
286
287         if (retval == ERROR_OK)
288                 retval = flash_erase_address_range(target, do_pad, address, length);
289
290         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
291                 command_print(CMD, "erased address " TARGET_ADDR_FMT " (length %" PRIu32 ")"
292                         " in %fs (%0.3f KiB/s)", address, length,
293                         duration_elapsed(&bench), duration_kbps(&bench, length));
294         }
295
296         return retval;
297 }
298
299 COMMAND_HANDLER(handle_flash_erase_command)
300 {
301         if (CMD_ARGC != 3)
302                 return ERROR_COMMAND_SYNTAX_ERROR;
303
304         uint32_t first;
305         uint32_t last;
306
307         struct flash_bank *p;
308         int retval;
309
310         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
311         if (retval != ERROR_OK)
312                 return retval;
313
314         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
315         if (strcmp(CMD_ARGV[2], "last") == 0)
316                 last = p->num_sectors - 1;
317         else
318                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
319
320         if (!(first <= last)) {
321                 command_print(CMD, "ERROR: "
322                         "first sector must be <= last");
323                 return ERROR_FAIL;
324         }
325
326         if (!(last <= (p->num_sectors - 1))) {
327                 command_print(CMD, "ERROR: "
328                         "last sector must be <= %u",
329                         p->num_sectors - 1);
330                 return ERROR_FAIL;
331         }
332
333         struct duration bench;
334         duration_start(&bench);
335
336         retval = flash_driver_erase(p, first, last);
337
338         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
339                 command_print(CMD, "erased sectors %" PRIu32 " "
340                         "through %" PRIu32 " on flash bank %u "
341                         "in %fs", first, last, p->bank_number, duration_elapsed(&bench));
342         }
343
344         return retval;
345 }
346
347 COMMAND_HANDLER(handle_flash_protect_command)
348 {
349         if (CMD_ARGC != 4)
350                 return ERROR_COMMAND_SYNTAX_ERROR;
351
352         uint32_t first;
353         uint32_t last;
354
355         struct flash_bank *p;
356         int retval;
357         int num_blocks;
358
359         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
360         if (retval != ERROR_OK)
361                 return retval;
362
363         if (p->num_prot_blocks)
364                 num_blocks = p->num_prot_blocks;
365         else
366                 num_blocks = p->num_sectors;
367
368         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
369         if (strcmp(CMD_ARGV[2], "last") == 0)
370                 last = num_blocks - 1;
371         else
372                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
373
374         bool set;
375         COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
376
377         if (!(first <= last)) {
378                 command_print(CMD, "ERROR: "
379                         "first %s must be <= last",
380                         (p->num_prot_blocks) ? "block" : "sector");
381                 return ERROR_FAIL;
382         }
383
384         if (!(last <= (uint32_t)(num_blocks - 1))) {
385                 command_print(CMD, "ERROR: "
386                         "last %s must be <= %d",
387                         (p->num_prot_blocks) ? "block" : "sector",
388                         num_blocks - 1);
389                 return ERROR_FAIL;
390         }
391
392         retval = flash_driver_protect(p, set, first, last);
393         if (retval == ERROR_OK) {
394                 command_print(CMD, "%s protection for %s %" PRIu32
395                         " through %" PRIu32 " on flash bank %d",
396                         (set) ? "set" : "cleared",
397                         (p->num_prot_blocks) ? "blocks" : "sectors",
398                         first, last, p->bank_number);
399         }
400
401         return retval;
402 }
403
404 COMMAND_HANDLER(handle_flash_write_image_command)
405 {
406         struct target *target = get_current_target(CMD_CTX);
407
408         struct image image;
409         uint32_t written;
410
411         int retval;
412
413         /* flash auto-erase is disabled by default*/
414         int auto_erase = 0;
415         bool auto_unlock = false;
416
417         while (CMD_ARGC) {
418                 if (strcmp(CMD_ARGV[0], "erase") == 0) {
419                         auto_erase = 1;
420                         CMD_ARGV++;
421                         CMD_ARGC--;
422                         command_print(CMD, "auto erase enabled");
423                 } else if (strcmp(CMD_ARGV[0], "unlock") == 0) {
424                         auto_unlock = true;
425                         CMD_ARGV++;
426                         CMD_ARGC--;
427                         command_print(CMD, "auto unlock enabled");
428                 } else
429                         break;
430         }
431
432         if (CMD_ARGC < 1)
433                 return ERROR_COMMAND_SYNTAX_ERROR;
434
435         if (!target) {
436                 LOG_ERROR("no target selected");
437                 return ERROR_FAIL;
438         }
439
440         struct duration bench;
441         duration_start(&bench);
442
443         if (CMD_ARGC >= 2) {
444                 image.base_address_set = true;
445                 COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
446         } else {
447                 image.base_address_set = false;
448                 image.base_address = 0x0;
449         }
450
451         image.start_address_set = false;
452
453         retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
454         if (retval != ERROR_OK)
455                 return retval;
456
457         retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
458         if (retval != ERROR_OK) {
459                 image_close(&image);
460                 return retval;
461         }
462
463         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
464                 command_print(CMD, "wrote %" PRIu32 " bytes from file %s "
465                         "in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
466                         duration_elapsed(&bench), duration_kbps(&bench, written));
467         }
468
469         image_close(&image);
470
471         return retval;
472 }
473
474 COMMAND_HANDLER(handle_flash_fill_command)
475 {
476         target_addr_t address;
477         uint64_t pattern;
478         uint32_t count;
479         struct target *target = get_current_target(CMD_CTX);
480         unsigned i;
481         uint32_t wordsize;
482         int retval;
483
484         if (CMD_ARGC != 3)
485                 return ERROR_COMMAND_SYNTAX_ERROR;
486
487         COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
488         COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], pattern);
489         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
490
491         struct flash_bank *bank;
492         retval = get_flash_bank_by_addr(target, address, true, &bank);
493         if (retval != ERROR_OK)
494                 return retval;
495
496         switch (CMD_NAME[4]) {
497                 case 'd':
498                         wordsize = 8;
499                         break;
500                 case 'w':
501                         wordsize = 4;
502                         break;
503                 case 'h':
504                         wordsize = 2;
505                         break;
506                 case 'b':
507                         wordsize = 1;
508                         break;
509                 default:
510                         return ERROR_COMMAND_SYNTAX_ERROR;
511         }
512
513         if ((wordsize < sizeof(pattern)) && (pattern >> (8 * wordsize) != 0)) {
514                 command_print(CMD, "Fill pattern 0x%" PRIx64 " does not fit within %" PRIu32 "-byte word", pattern, wordsize);
515                 return ERROR_FAIL;
516         }
517
518         if (count == 0)
519                 return ERROR_OK;
520
521         if (address + count * wordsize > bank->base + bank->size) {
522                 LOG_ERROR("Cannot cross flash bank borders");
523                 return ERROR_FAIL;
524         }
525
526         uint32_t size_bytes = count * wordsize;
527         target_addr_t aligned_start = flash_write_align_start(bank, address);
528         target_addr_t end_addr = address + size_bytes - 1;
529         target_addr_t aligned_end = flash_write_align_end(bank, end_addr);
530         uint32_t aligned_size = aligned_end + 1 - aligned_start;
531         uint32_t padding_at_start = address - aligned_start;
532         uint32_t padding_at_end = aligned_end - end_addr;
533
534         uint8_t *buffer = malloc(aligned_size);
535         if (buffer == NULL)
536                 return ERROR_FAIL;
537
538         if (padding_at_start) {
539                 memset(buffer, bank->default_padded_value, padding_at_start);
540                 LOG_WARNING("Start address " TARGET_ADDR_FMT
541                         " breaks the required alignment of flash bank %s",
542                         address, bank->name);
543                 LOG_WARNING("Padding %" PRIu32 " bytes from " TARGET_ADDR_FMT,
544                     padding_at_start, aligned_start);
545         }
546
547         uint8_t *ptr = buffer + padding_at_start;
548
549         switch (wordsize) {
550                 case 8:
551                         for (i = 0; i < count; i++, ptr += wordsize)
552                                 target_buffer_set_u64(target, ptr, pattern);
553                         break;
554                 case 4:
555                         for (i = 0; i < count; i++, ptr += wordsize)
556                                 target_buffer_set_u32(target, ptr, pattern);
557                         break;
558                 case 2:
559                         for (i = 0; i < count; i++, ptr += wordsize)
560                                 target_buffer_set_u16(target, ptr, pattern);
561                         break;
562                 case 1:
563                         memset(ptr, pattern, count);
564                         ptr += count;
565                         break;
566                 default:
567                         LOG_ERROR("BUG: can't happen");
568                         exit(-1);
569         }
570
571         if (padding_at_end) {
572                 memset(ptr, bank->default_padded_value, padding_at_end);
573                 LOG_INFO("Padding at " TARGET_ADDR_FMT " with %" PRIu32
574                         " bytes (bank write end alignment)",
575                         end_addr + 1, padding_at_end);
576         }
577
578         struct duration bench;
579         duration_start(&bench);
580
581         retval = flash_driver_write(bank, buffer, aligned_start - bank->base, aligned_size);
582         if (retval != ERROR_OK)
583                 goto done;
584
585         retval = flash_driver_read(bank, buffer, address - bank->base, size_bytes);
586         if (retval != ERROR_OK)
587                 goto done;
588
589         for (i = 0, ptr = buffer; i < count; i++) {
590                 uint64_t readback = 0;
591
592                 switch (wordsize) {
593                         case 8:
594                                 readback = target_buffer_get_u64(target, ptr);
595                                 break;
596                         case 4:
597                                 readback = target_buffer_get_u32(target, ptr);
598                                 break;
599                         case 2:
600                                 readback = target_buffer_get_u16(target, ptr);
601                                 break;
602                         case 1:
603                                 readback = *ptr;
604                                 break;
605                 }
606                 if (readback != pattern) {
607                         LOG_ERROR(
608                                 "Verification error address " TARGET_ADDR_FMT
609                                 ", read back 0x%02" PRIx64 ", expected 0x%02" PRIx64,
610                                 address + i * wordsize, readback, pattern);
611                         retval = ERROR_FAIL;
612                         goto done;
613                 }
614                 ptr += wordsize;
615         }
616
617         if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) {
618                 command_print(CMD, "wrote %" PRIu32 " bytes to " TARGET_ADDR_FMT
619                         " in %fs (%0.3f KiB/s)", size_bytes, address,
620                         duration_elapsed(&bench), duration_kbps(&bench, size_bytes));
621         }
622
623 done:
624         free(buffer);
625
626         return retval;
627 }
628
629 COMMAND_HANDLER(handle_flash_md_command)
630 {
631         int retval;
632
633         if (CMD_ARGC < 1 || CMD_ARGC > 2)
634                 return ERROR_COMMAND_SYNTAX_ERROR;
635
636         target_addr_t address;
637         COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
638
639         uint32_t count = 1;
640         if (CMD_ARGC == 2)
641                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count);
642
643         unsigned int wordsize;
644         switch (CMD_NAME[2]) {
645                 case 'w':
646                         wordsize = 4;
647                         break;
648                 case 'h':
649                         wordsize = 2;
650                         break;
651                 case 'b':
652                         wordsize = 1;
653                         break;
654                 default:
655                         return ERROR_COMMAND_SYNTAX_ERROR;
656         }
657
658         if (count == 0)
659                 return ERROR_OK;
660
661         struct target *target = get_current_target(CMD_CTX);
662         struct flash_bank *bank;
663         retval = get_flash_bank_by_addr(target, address, true, &bank);
664         if (retval != ERROR_OK)
665                 return retval;
666
667         uint32_t offset = address - bank->base;
668         uint32_t sizebytes = count * wordsize;
669         if (offset + sizebytes > bank->size) {
670                 command_print(CMD, "Cannot cross flash bank borders");
671                 return ERROR_FAIL;
672         }
673
674         uint8_t *buffer = calloc(count, wordsize);
675         if (buffer == NULL) {
676                 command_print(CMD, "No memory for flash read buffer");
677                 return ERROR_FAIL;
678         }
679
680         retval = flash_driver_read(bank, buffer, offset, sizebytes);
681         if (retval == ERROR_OK)
682                 target_handle_md_output(CMD, target, address, wordsize, count, buffer);
683
684         free(buffer);
685
686         return retval;
687 }
688
689
690 COMMAND_HANDLER(handle_flash_write_bank_command)
691 {
692         uint32_t offset;
693         uint8_t *buffer;
694         size_t length;
695         struct fileio *fileio;
696
697         if (CMD_ARGC < 2 || CMD_ARGC > 3)
698                 return ERROR_COMMAND_SYNTAX_ERROR;
699
700         struct duration bench;
701         duration_start(&bench);
702
703         struct flash_bank *bank;
704         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
705         if (ERROR_OK != retval)
706                 return retval;
707
708         offset = 0;
709
710         if (CMD_ARGC > 2)
711                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
712
713         if (offset > bank->size) {
714                 LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
715                         offset);
716                 return ERROR_COMMAND_ARGUMENT_INVALID;
717         }
718
719         if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
720                 return ERROR_FAIL;
721
722         size_t filesize;
723         retval = fileio_size(fileio, &filesize);
724         if (retval != ERROR_OK) {
725                 fileio_close(fileio);
726                 return retval;
727         }
728
729         length = MIN(filesize, bank->size - offset);
730
731         if (!length) {
732                 LOG_INFO("Nothing to write to flash bank");
733                 fileio_close(fileio);
734                 return ERROR_OK;
735         }
736
737         if (length != filesize)
738                 LOG_INFO("File content exceeds flash bank size. Only writing the "
739                         "first %zu bytes of the file", length);
740
741         target_addr_t start_addr = bank->base + offset;
742         target_addr_t aligned_start = flash_write_align_start(bank, start_addr);
743         target_addr_t end_addr = start_addr + length - 1;
744         target_addr_t aligned_end = flash_write_align_end(bank, end_addr);
745         uint32_t aligned_size = aligned_end + 1 - aligned_start;
746         uint32_t padding_at_start = start_addr - aligned_start;
747         uint32_t padding_at_end = aligned_end - end_addr;
748
749         buffer = malloc(aligned_size);
750         if (buffer == NULL) {
751                 fileio_close(fileio);
752                 LOG_ERROR("Out of memory");
753                 return ERROR_FAIL;
754         }
755
756         if (padding_at_start) {
757                 memset(buffer, bank->default_padded_value, padding_at_start);
758                 LOG_WARNING("Start offset 0x%08" PRIx32
759                         " breaks the required alignment of flash bank %s",
760                         offset, bank->name);
761                 LOG_WARNING("Padding %" PRIu32 " bytes from " TARGET_ADDR_FMT,
762                     padding_at_start, aligned_start);
763         }
764
765         uint8_t *ptr = buffer + padding_at_start;
766         size_t buf_cnt;
767         if (fileio_read(fileio, length, ptr, &buf_cnt) != ERROR_OK) {
768                 free(buffer);
769                 fileio_close(fileio);
770                 return ERROR_FAIL;
771         }
772
773         if (buf_cnt != length) {
774                 LOG_ERROR("Short read");
775                 free(buffer);
776                 return ERROR_FAIL;
777         }
778
779         ptr += length;
780
781         if (padding_at_end) {
782                 memset(ptr, bank->default_padded_value, padding_at_end);
783                 LOG_INFO("Padding at " TARGET_ADDR_FMT " with %" PRIu32
784                         " bytes (bank write end alignment)",
785                         end_addr + 1, padding_at_end);
786         }
787
788         retval = flash_driver_write(bank, buffer, aligned_start - bank->base, aligned_size);
789
790         free(buffer);
791
792         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
793                 command_print(CMD, "wrote %zu bytes from file %s to flash bank %u"
794                         " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
795                         length, CMD_ARGV[1], bank->bank_number, offset,
796                         duration_elapsed(&bench), duration_kbps(&bench, length));
797         }
798
799         fileio_close(fileio);
800
801         return retval;
802 }
803
804 COMMAND_HANDLER(handle_flash_read_bank_command)
805 {
806         uint32_t offset;
807         uint8_t *buffer;
808         struct fileio *fileio;
809         uint32_t length;
810         size_t written;
811
812         if (CMD_ARGC < 2 || CMD_ARGC > 4)
813                 return ERROR_COMMAND_SYNTAX_ERROR;
814
815         struct duration bench;
816         duration_start(&bench);
817
818         struct flash_bank *p;
819         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
820
821         if (ERROR_OK != retval)
822                 return retval;
823
824         offset = 0;
825
826         if (CMD_ARGC > 2)
827                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
828
829         if (offset > p->size) {
830                 LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
831                         offset);
832                 return ERROR_COMMAND_ARGUMENT_INVALID;
833         }
834
835         length = p->size - offset;
836
837         if (CMD_ARGC > 3)
838                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length);
839
840         if (offset + length > p->size) {
841                 LOG_ERROR("Length of %" PRIu32 " bytes with offset 0x%8.8" PRIx32
842                         " is out of range of the flash bank", length, offset);
843                 return ERROR_COMMAND_ARGUMENT_INVALID;
844         }
845
846         buffer = malloc(length);
847         if (buffer == NULL) {
848                 LOG_ERROR("Out of memory");
849                 return ERROR_FAIL;
850         }
851
852         retval = flash_driver_read(p, buffer, offset, length);
853         if (retval != ERROR_OK) {
854                 LOG_ERROR("Read error");
855                 free(buffer);
856                 return retval;
857         }
858
859         retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
860         if (retval != ERROR_OK) {
861                 LOG_ERROR("Could not open file");
862                 free(buffer);
863                 return retval;
864         }
865
866         retval = fileio_write(fileio, length, buffer, &written);
867         fileio_close(fileio);
868         free(buffer);
869         if (retval != ERROR_OK) {
870                 LOG_ERROR("Could not write file");
871                 return ERROR_FAIL;
872         }
873
874         if (duration_measure(&bench) == ERROR_OK)
875                 command_print(CMD, "wrote %zd bytes to file %s from flash bank %u"
876                         " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
877                         written, CMD_ARGV[1], p->bank_number, offset,
878                         duration_elapsed(&bench), duration_kbps(&bench, written));
879
880         return retval;
881 }
882
883
884 COMMAND_HANDLER(handle_flash_verify_bank_command)
885 {
886         uint32_t offset;
887         uint8_t *buffer_file, *buffer_flash;
888         struct fileio *fileio;
889         size_t read_cnt;
890         size_t filesize;
891         size_t length;
892         int differ;
893
894         if (CMD_ARGC < 2 || CMD_ARGC > 3)
895                 return ERROR_COMMAND_SYNTAX_ERROR;
896
897         struct duration bench;
898         duration_start(&bench);
899
900         struct flash_bank *p;
901         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
902         if (ERROR_OK != retval)
903                 return retval;
904
905         offset = 0;
906
907         if (CMD_ARGC > 2)
908                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
909
910         if (offset > p->size) {
911                 LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
912                         offset);
913                 return ERROR_COMMAND_ARGUMENT_INVALID;
914         }
915
916         retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
917         if (retval != ERROR_OK) {
918                 LOG_ERROR("Could not open file");
919                 return retval;
920         }
921
922         retval = fileio_size(fileio, &filesize);
923         if (retval != ERROR_OK) {
924                 fileio_close(fileio);
925                 return retval;
926         }
927
928         length = MIN(filesize, p->size - offset);
929
930         if (!length) {
931                 LOG_INFO("Nothing to compare with flash bank");
932                 fileio_close(fileio);
933                 return ERROR_OK;
934         }
935
936         if (length != filesize)
937                 LOG_INFO("File content exceeds flash bank size. Only comparing the "
938                         "first %zu bytes of the file", length);
939
940         buffer_file = malloc(length);
941         if (buffer_file == NULL) {
942                 LOG_ERROR("Out of memory");
943                 fileio_close(fileio);
944                 return ERROR_FAIL;
945         }
946
947         retval = fileio_read(fileio, length, buffer_file, &read_cnt);
948         fileio_close(fileio);
949         if (retval != ERROR_OK) {
950                 LOG_ERROR("File read failure");
951                 free(buffer_file);
952                 return retval;
953         }
954
955         if (read_cnt != length) {
956                 LOG_ERROR("Short read");
957                 free(buffer_file);
958                 return ERROR_FAIL;
959         }
960
961         buffer_flash = malloc(length);
962         if (buffer_flash == NULL) {
963                 LOG_ERROR("Out of memory");
964                 free(buffer_file);
965                 return ERROR_FAIL;
966         }
967
968         retval = flash_driver_read(p, buffer_flash, offset, length);
969         if (retval != ERROR_OK) {
970                 LOG_ERROR("Flash read error");
971                 free(buffer_flash);
972                 free(buffer_file);
973                 return retval;
974         }
975
976         if (duration_measure(&bench) == ERROR_OK)
977                 command_print(CMD, "read %zd bytes from file %s and flash bank %u"
978                         " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
979                         length, CMD_ARGV[1], p->bank_number, offset,
980                         duration_elapsed(&bench), duration_kbps(&bench, length));
981
982         differ = memcmp(buffer_file, buffer_flash, length);
983         command_print(CMD, "contents %s", differ ? "differ" : "match");
984         if (differ) {
985                 uint32_t t;
986                 int diffs = 0;
987                 for (t = 0; t < length; t++) {
988                         if (buffer_flash[t] == buffer_file[t])
989                                 continue;
990                         command_print(CMD, "diff %d address 0x%08" PRIx32 ". Was 0x%02x instead of 0x%02x",
991                                         diffs, t + offset, buffer_flash[t], buffer_file[t]);
992                         if (diffs++ >= 127) {
993                                 command_print(CMD, "More than 128 errors, the rest are not printed.");
994                                 break;
995                         }
996                         keep_alive();
997                 }
998         }
999         free(buffer_flash);
1000         free(buffer_file);
1001
1002         return differ ? ERROR_FAIL : ERROR_OK;
1003 }
1004
1005 void flash_set_dirty(void)
1006 {
1007         struct flash_bank *c;
1008
1009         /* set all flash to require erasing */
1010         for (c = flash_bank_list(); c; c = c->next) {
1011                 for (unsigned int i = 0; i < c->num_sectors; i++)
1012                         c->sectors[i].is_erased = 0;
1013         }
1014 }
1015
1016 COMMAND_HANDLER(handle_flash_padded_value_command)
1017 {
1018         if (CMD_ARGC != 2)
1019                 return ERROR_COMMAND_SYNTAX_ERROR;
1020
1021         struct flash_bank *p;
1022         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
1023         if (ERROR_OK != retval)
1024                 return retval;
1025
1026         COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value);
1027
1028         command_print(CMD, "Default padded value set to 0x%" PRIx8 " for flash bank %u",
1029                         p->default_padded_value, p->bank_number);
1030
1031         return retval;
1032 }
1033
1034 static const struct command_registration flash_exec_command_handlers[] = {
1035         {
1036                 .name = "probe",
1037                 .handler = handle_flash_probe_command,
1038                 .mode = COMMAND_EXEC,
1039                 .usage = "bank_id",
1040                 .help = "Identify a flash bank.",
1041         },
1042         {
1043                 .name = "info",
1044                 .handler = handle_flash_info_command,
1045                 .mode = COMMAND_EXEC,
1046                 .usage = "bank_id ['sectors']",
1047                 .help = "Print information about a flash bank.",
1048         },
1049         {
1050                 .name = "erase_check",
1051                 .handler = handle_flash_erase_check_command,
1052                 .mode = COMMAND_EXEC,
1053                 .usage = "bank_id",
1054                 .help = "Check erase state of all blocks in a "
1055                         "flash bank.",
1056         },
1057         {
1058                 .name = "erase_sector",
1059                 .handler = handle_flash_erase_command,
1060                 .mode = COMMAND_EXEC,
1061                 .usage = "bank_id first_sector_num (last_sector_num|'last')",
1062                 .help = "Erase a range of sectors in a flash bank.",
1063         },
1064         {
1065                 .name = "erase_address",
1066                 .handler = handle_flash_erase_address_command,
1067                 .mode = COMMAND_EXEC,
1068                 .usage = "['pad'] ['unlock'] address length",
1069                 .help = "Erase flash sectors starting at address and "
1070                         "continuing for length bytes.  If 'pad' is specified, "
1071                         "data outside that range may also be erased: the start "
1072                         "address may be decreased, and length increased, so "
1073                         "that all of the first and last sectors are erased. "
1074                         "If 'unlock' is specified, then the flash is unprotected "
1075                         "before erasing.",
1076
1077         },
1078         {
1079                 .name = "filld",
1080                 .handler = handle_flash_fill_command,
1081                 .mode = COMMAND_EXEC,
1082                 .usage = "address value n",
1083                 .help = "Fill n double-words with 64-bit value, starting at "
1084                         "word address.  (No autoerase.)",
1085         },
1086         {
1087                 .name = "fillw",
1088                 .handler = handle_flash_fill_command,
1089                 .mode = COMMAND_EXEC,
1090                 .usage = "address value n",
1091                 .help = "Fill n words with 32-bit value, starting at "
1092                         "word address.  (No autoerase.)",
1093         },
1094         {
1095                 .name = "fillh",
1096                 .handler = handle_flash_fill_command,
1097                 .mode = COMMAND_EXEC,
1098                 .usage = "address value n",
1099                 .help = "Fill n halfwords with 16-bit value, starting at "
1100                         "word address.  (No autoerase.)",
1101         },
1102         {
1103                 .name = "fillb",
1104                 .handler = handle_flash_fill_command,
1105                 .mode = COMMAND_EXEC,
1106                 .usage = "address value n",
1107                 .help = "Fill n bytes with 8-bit value, starting at "
1108                         "word address.  (No autoerase.)",
1109         },
1110         {
1111                 .name = "mdb",
1112                 .handler = handle_flash_md_command,
1113                 .mode = COMMAND_EXEC,
1114                 .usage = "address [count]",
1115                 .help = "Display bytes from flash.",
1116         },
1117         {
1118                 .name = "mdh",
1119                 .handler = handle_flash_md_command,
1120                 .mode = COMMAND_EXEC,
1121                 .usage = "address [count]",
1122                 .help = "Display half-words from flash.",
1123         },
1124         {
1125                 .name = "mdw",
1126                 .handler = handle_flash_md_command,
1127                 .mode = COMMAND_EXEC,
1128                 .usage = "address [count]",
1129                 .help = "Display words from flash.",
1130         },
1131         {
1132                 .name = "write_bank",
1133                 .handler = handle_flash_write_bank_command,
1134                 .mode = COMMAND_EXEC,
1135                 .usage = "bank_id filename [offset]",
1136                 .help = "Write binary data from file to flash bank. Allow optional "
1137                         "offset from beginning of the bank (defaults to zero).",
1138         },
1139         {
1140                 .name = "write_image",
1141                 .handler = handle_flash_write_image_command,
1142                 .mode = COMMAND_EXEC,
1143                 .usage = "[erase] [unlock] filename [offset [file_type]]",
1144                 .help = "Write an image to flash.  Optionally first unprotect "
1145                         "and/or erase the region to be used.  Allow optional "
1146                         "offset from beginning of bank (defaults to zero)",
1147         },
1148         {
1149                 .name = "read_bank",
1150                 .handler = handle_flash_read_bank_command,
1151                 .mode = COMMAND_EXEC,
1152                 .usage = "bank_id filename [offset [length]]",
1153                 .help = "Read binary data from flash bank to file. Allow optional "
1154                         "offset from beginning of the bank (defaults to zero).",
1155         },
1156         {
1157                 .name = "verify_bank",
1158                 .handler = handle_flash_verify_bank_command,
1159                 .mode = COMMAND_EXEC,
1160                 .usage = "bank_id filename [offset]",
1161                 .help = "Compare the contents of a file with the contents of the "
1162                         "flash bank. Allow optional offset from beginning of the bank "
1163                         "(defaults to zero).",
1164         },
1165         {
1166                 .name = "protect",
1167                 .handler = handle_flash_protect_command,
1168                 .mode = COMMAND_EXEC,
1169                 .usage = "bank_id first_block [last_block|'last'] "
1170                         "('on'|'off')",
1171                 .help = "Turn protection on or off for a range of protection "
1172                         "blocks or sectors in a given flash bank. "
1173                         "See 'flash info' output for a list of blocks.",
1174         },
1175         {
1176                 .name = "padded_value",
1177                 .handler = handle_flash_padded_value_command,
1178                 .mode = COMMAND_EXEC,
1179                 .usage = "bank_id value",
1180                 .help = "Set default flash padded value",
1181         },
1182         COMMAND_REGISTRATION_DONE
1183 };
1184
1185 static int flash_init_drivers(struct command_context *cmd_ctx)
1186 {
1187         if (!flash_bank_list())
1188                 return ERROR_OK;
1189
1190         struct command *parent = command_find_in_context(cmd_ctx, "flash");
1191         return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
1192 }
1193
1194 COMMAND_HANDLER(handle_flash_bank_command)
1195 {
1196         if (CMD_ARGC < 7) {
1197                 LOG_ERROR("usage: flash bank <name> <driver> "
1198                         "<base> <size> <chip_width> <bus_width> <target>");
1199                 return ERROR_COMMAND_SYNTAX_ERROR;
1200         }
1201         /* save bank name and advance arguments for compatibility */
1202         const char *bank_name = *CMD_ARGV++;
1203         CMD_ARGC--;
1204
1205         struct target *target = get_target(CMD_ARGV[5]);
1206         if (target == NULL) {
1207                 LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
1208                 return ERROR_FAIL;
1209         }
1210
1211         const char *driver_name = CMD_ARGV[0];
1212         const struct flash_driver *driver = flash_driver_find_by_name(driver_name);
1213         if (NULL == driver) {
1214                 /* no matching flash driver found */
1215                 LOG_ERROR("flash driver '%s' not found", driver_name);
1216                 return ERROR_FAIL;
1217         }
1218
1219         /* check the flash bank name is unique */
1220         if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
1221                 /* flash bank name already exists  */
1222                 LOG_ERROR("flash bank name '%s' already exists", bank_name);
1223                 return ERROR_FAIL;
1224         }
1225
1226         /* register flash specific commands */
1227         if (NULL != driver->commands) {
1228                 int retval = register_commands(CMD_CTX, NULL,
1229                                 driver->commands);
1230                 if (ERROR_OK != retval) {
1231                         LOG_ERROR("couldn't register '%s' commands",
1232                                 driver_name);
1233                         return ERROR_FAIL;
1234                 }
1235         }
1236
1237         struct flash_bank *c = calloc(1, sizeof(*c));
1238         c->name = strdup(bank_name);
1239         c->target = target;
1240         c->driver = driver;
1241         COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[1], c->base);
1242         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
1243         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[3], c->chip_width);
1244         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[4], c->bus_width);
1245         c->default_padded_value = c->erased_value = 0xff;
1246         c->minimal_write_gap = FLASH_WRITE_GAP_SECTOR;
1247
1248         int retval;
1249         retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
1250         if (ERROR_OK != retval) {
1251                 LOG_ERROR("'%s' driver rejected flash bank at " TARGET_ADDR_FMT
1252                                 "; usage: %s", driver_name, c->base, driver->usage);
1253                 free(c);
1254                 return retval;
1255         }
1256
1257         if (driver->usage == NULL)
1258                 LOG_DEBUG("'%s' driver usage field missing", driver_name);
1259
1260         flash_bank_add(c);
1261
1262         return ERROR_OK;
1263 }
1264
1265 COMMAND_HANDLER(handle_flash_banks_command)
1266 {
1267         if (CMD_ARGC != 0)
1268                 return ERROR_COMMAND_SYNTAX_ERROR;
1269
1270         unsigned n = 0;
1271         for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
1272                 command_print(CMD, "#%d : %s (%s) at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32 ", "
1273                         "buswidth %u, chipwidth %u", p->bank_number,
1274                         p->name, p->driver->name, p->base, p->size,
1275                         p->bus_width, p->chip_width);
1276         }
1277         return ERROR_OK;
1278 }
1279
1280 static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
1281 {
1282         if (argc != 1) {
1283                 Jim_WrongNumArgs(interp, 1, argv,
1284                         "no arguments to 'flash list' command");
1285                 return JIM_ERR;
1286         }
1287
1288         Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
1289
1290         for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
1291                 Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
1292
1293                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
1294                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
1295                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
1296                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
1297                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
1298                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
1299                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
1300                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
1301                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
1302                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
1303
1304                 Jim_ListAppendElement(interp, list, elem);
1305         }
1306
1307         Jim_SetResult(interp, list);
1308
1309         return JIM_OK;
1310 }
1311
1312 COMMAND_HANDLER(handle_flash_init_command)
1313 {
1314         if (CMD_ARGC != 0)
1315                 return ERROR_COMMAND_SYNTAX_ERROR;
1316
1317         static bool flash_initialized;
1318         if (flash_initialized) {
1319                 LOG_INFO("'flash init' has already been called");
1320                 return ERROR_OK;
1321         }
1322         flash_initialized = true;
1323
1324         LOG_DEBUG("Initializing flash devices...");
1325         return flash_init_drivers(CMD_CTX);
1326 }
1327
1328 static const struct command_registration flash_config_command_handlers[] = {
1329         {
1330                 .name = "bank",
1331                 .handler = handle_flash_bank_command,
1332                 .mode = COMMAND_CONFIG,
1333                 .usage = "bank_id driver_name base_address size_bytes "
1334                         "chip_width_bytes bus_width_bytes target "
1335                         "[driver_options ...]",
1336                 .help = "Define a new bank with the given name, "
1337                         "using the specified NOR flash driver.",
1338         },
1339         {
1340                 .name = "init",
1341                 .mode = COMMAND_CONFIG,
1342                 .handler = handle_flash_init_command,
1343                 .help = "Initialize flash devices.",
1344                 .usage = "",
1345         },
1346         {
1347                 .name = "banks",
1348                 .mode = COMMAND_ANY,
1349                 .handler = handle_flash_banks_command,
1350                 .help = "Display table with information about flash banks.",
1351                 .usage = "",
1352         },
1353         {
1354                 .name = "list",
1355                 .mode = COMMAND_ANY,
1356                 .jim_handler = jim_flash_list,
1357                 .help = "Returns a list of details about the flash banks.",
1358         },
1359         COMMAND_REGISTRATION_DONE
1360 };
1361 static const struct command_registration flash_command_handlers[] = {
1362         {
1363                 .name = "flash",
1364                 .mode = COMMAND_ANY,
1365                 .help = "NOR flash command group",
1366                 .chain = flash_config_command_handlers,
1367                 .usage = "",
1368         },
1369         COMMAND_REGISTRATION_DONE
1370 };
1371
1372 int flash_register_commands(struct command_context *cmd_ctx)
1373 {
1374         return register_commands(cmd_ctx, NULL, flash_command_handlers);
1375 }