flash/nor: Use proper data types in driver API
[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 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 " %" PRIi32 "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 " %" PRIi32 "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 %"
292                                 PRIi32 ")"
293                         " in %fs (%0.3f KiB/s)", address, length,
294                         duration_elapsed(&bench), duration_kbps(&bench, length));
295         }
296
297         return retval;
298 }
299
300 COMMAND_HANDLER(handle_flash_erase_command)
301 {
302         if (CMD_ARGC != 3)
303                 return ERROR_COMMAND_SYNTAX_ERROR;
304
305         uint32_t first;
306         uint32_t last;
307
308         struct flash_bank *p;
309         int retval;
310
311         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
312         if (retval != ERROR_OK)
313                 return retval;
314
315         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
316         if (strcmp(CMD_ARGV[2], "last") == 0)
317                 last = p->num_sectors - 1;
318         else
319                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
320
321         if (!(first <= last)) {
322                 command_print(CMD, "ERROR: "
323                         "first sector must be <= last");
324                 return ERROR_FAIL;
325         }
326
327         if (!(last <= (p->num_sectors - 1))) {
328                 command_print(CMD, "ERROR: "
329                         "last sector must be <= %" PRIu32,
330                         p->num_sectors - 1);
331                 return ERROR_FAIL;
332         }
333
334         struct duration bench;
335         duration_start(&bench);
336
337         retval = flash_driver_erase(p, first, last);
338
339         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
340                 command_print(CMD, "erased sectors %" PRIu32 " "
341                         "through %" PRIu32 " on flash bank %u "
342                         "in %fs", first, last, p->bank_number, duration_elapsed(&bench));
343         }
344
345         return retval;
346 }
347
348 COMMAND_HANDLER(handle_flash_protect_command)
349 {
350         if (CMD_ARGC != 4)
351                 return ERROR_COMMAND_SYNTAX_ERROR;
352
353         uint32_t first;
354         uint32_t last;
355
356         struct flash_bank *p;
357         int retval;
358         int num_blocks;
359
360         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
361         if (retval != ERROR_OK)
362                 return retval;
363
364         if (p->num_prot_blocks)
365                 num_blocks = p->num_prot_blocks;
366         else
367                 num_blocks = p->num_sectors;
368
369         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
370         if (strcmp(CMD_ARGV[2], "last") == 0)
371                 last = num_blocks - 1;
372         else
373                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
374
375         bool set;
376         COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
377
378         if (!(first <= last)) {
379                 command_print(CMD, "ERROR: "
380                         "first %s must be <= last",
381                         (p->num_prot_blocks) ? "block" : "sector");
382                 return ERROR_FAIL;
383         }
384
385         if (!(last <= (uint32_t)(num_blocks - 1))) {
386                 command_print(CMD, "ERROR: "
387                         "last %s must be <= %" PRIu32,
388                         (p->num_prot_blocks) ? "block" : "sector",
389                         num_blocks - 1);
390                 return ERROR_FAIL;
391         }
392
393         retval = flash_driver_protect(p, set, first, last);
394         if (retval == ERROR_OK) {
395                 command_print(CMD, "%s protection for %s %" PRIu32
396                         " through %" PRIu32 " on flash bank %d",
397                         (set) ? "set" : "cleared",
398                         (p->num_prot_blocks) ? "blocks" : "sectors",
399                         first, last, p->bank_number);
400         }
401
402         return retval;
403 }
404
405 COMMAND_HANDLER(handle_flash_write_image_command)
406 {
407         struct target *target = get_current_target(CMD_CTX);
408
409         struct image image;
410         uint32_t written;
411
412         int retval;
413
414         /* flash auto-erase is disabled by default*/
415         int auto_erase = 0;
416         bool auto_unlock = false;
417
418         while (CMD_ARGC) {
419                 if (strcmp(CMD_ARGV[0], "erase") == 0) {
420                         auto_erase = 1;
421                         CMD_ARGV++;
422                         CMD_ARGC--;
423                         command_print(CMD, "auto erase enabled");
424                 } else if (strcmp(CMD_ARGV[0], "unlock") == 0) {
425                         auto_unlock = true;
426                         CMD_ARGV++;
427                         CMD_ARGC--;
428                         command_print(CMD, "auto unlock enabled");
429                 } else
430                         break;
431         }
432
433         if (CMD_ARGC < 1)
434                 return ERROR_COMMAND_SYNTAX_ERROR;
435
436         if (!target) {
437                 LOG_ERROR("no target selected");
438                 return ERROR_FAIL;
439         }
440
441         struct duration bench;
442         duration_start(&bench);
443
444         if (CMD_ARGC >= 2) {
445                 image.base_address_set = 1;
446                 COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
447         } else {
448                 image.base_address_set = 0;
449                 image.base_address = 0x0;
450         }
451
452         image.start_address_set = 0;
453
454         retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
455         if (retval != ERROR_OK)
456                 return retval;
457
458         retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
459         if (retval != ERROR_OK) {
460                 image_close(&image);
461                 return retval;
462         }
463
464         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
465                 command_print(CMD, "wrote %" PRIu32 " bytes from file %s "
466                         "in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
467                         duration_elapsed(&bench), duration_kbps(&bench, written));
468         }
469
470         image_close(&image);
471
472         return retval;
473 }
474
475 COMMAND_HANDLER(handle_flash_fill_command)
476 {
477         target_addr_t address;
478         uint64_t pattern;
479         uint32_t count;
480         struct target *target = get_current_target(CMD_CTX);
481         unsigned i;
482         uint32_t wordsize;
483         int retval;
484
485         if (CMD_ARGC != 3)
486                 return ERROR_COMMAND_SYNTAX_ERROR;
487
488         COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
489         COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], pattern);
490         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
491
492         struct flash_bank *bank;
493         retval = get_flash_bank_by_addr(target, address, true, &bank);
494         if (retval != ERROR_OK)
495                 return retval;
496
497         switch (CMD_NAME[4]) {
498                 case 'd':
499                         wordsize = 8;
500                         break;
501                 case 'w':
502                         wordsize = 4;
503                         break;
504                 case 'h':
505                         wordsize = 2;
506                         break;
507                 case 'b':
508                         wordsize = 1;
509                         break;
510                 default:
511                         return ERROR_COMMAND_SYNTAX_ERROR;
512         }
513
514         if ((wordsize < sizeof(pattern)) && (pattern >> (8 * wordsize) != 0)) {
515                 command_print(CMD, "Fill pattern 0x%" PRIx64 " does not fit within %" PRIu32 "-byte word", pattern, wordsize);
516                 return ERROR_FAIL;
517         }
518
519         if (count == 0)
520                 return ERROR_OK;
521
522         if (address + count * wordsize > bank->base + bank->size) {
523                 LOG_ERROR("Cannot cross flash bank borders");
524                 return ERROR_FAIL;
525         }
526
527         uint32_t size_bytes = count * wordsize;
528         target_addr_t aligned_start = flash_write_align_start(bank, address);
529         target_addr_t end_addr = address + size_bytes - 1;
530         target_addr_t aligned_end = flash_write_align_end(bank, end_addr);
531         uint32_t aligned_size = aligned_end + 1 - aligned_start;
532         uint32_t padding_at_start = address - aligned_start;
533         uint32_t padding_at_end = aligned_end - end_addr;
534
535         uint8_t *buffer = malloc(aligned_size);
536         if (buffer == NULL)
537                 return ERROR_FAIL;
538
539         if (padding_at_start) {
540                 memset(buffer, bank->default_padded_value, padding_at_start);
541                 LOG_WARNING("Start address " TARGET_ADDR_FMT
542                         " breaks the required alignment of flash bank %s",
543                         address, bank->name);
544                 LOG_WARNING("Padding %" PRId32 " bytes from " TARGET_ADDR_FMT,
545                     padding_at_start, aligned_start);
546         }
547
548         uint8_t *ptr = buffer + padding_at_start;
549
550         switch (wordsize) {
551                 case 8:
552                         for (i = 0; i < count; i++, ptr += wordsize)
553                                 target_buffer_set_u64(target, ptr, pattern);
554                         break;
555                 case 4:
556                         for (i = 0; i < count; i++, ptr += wordsize)
557                                 target_buffer_set_u32(target, ptr, pattern);
558                         break;
559                 case 2:
560                         for (i = 0; i < count; i++, ptr += wordsize)
561                                 target_buffer_set_u16(target, ptr, pattern);
562                         break;
563                 case 1:
564                         memset(ptr, pattern, count);
565                         ptr += count;
566                         break;
567                 default:
568                         LOG_ERROR("BUG: can't happen");
569                         exit(-1);
570         }
571
572         if (padding_at_end) {
573                 memset(ptr, bank->default_padded_value, padding_at_end);
574                 LOG_INFO("Padding at " TARGET_ADDR_FMT " with %" PRId32
575                         " bytes (bank write end alignment)",
576                         end_addr + 1, padding_at_end);
577         }
578
579         struct duration bench;
580         duration_start(&bench);
581
582         retval = flash_driver_write(bank, buffer, aligned_start - bank->base, aligned_size);
583         if (retval != ERROR_OK)
584                 goto done;
585
586         retval = flash_driver_read(bank, buffer, address - bank->base, size_bytes);
587         if (retval != ERROR_OK)
588                 goto done;
589
590         for (i = 0, ptr = buffer; i < count; i++) {
591                 uint64_t readback = 0;
592
593                 switch (wordsize) {
594                         case 8:
595                                 readback = target_buffer_get_u64(target, ptr);
596                                 break;
597                         case 4:
598                                 readback = target_buffer_get_u32(target, ptr);
599                                 break;
600                         case 2:
601                                 readback = target_buffer_get_u16(target, ptr);
602                                 break;
603                         case 1:
604                                 readback = *ptr;
605                                 break;
606                 }
607                 if (readback != pattern) {
608                         LOG_ERROR(
609                                 "Verification error address " TARGET_ADDR_FMT
610                                 ", read back 0x%02" PRIx64 ", expected 0x%02" PRIx64,
611                                 address + i * wordsize, readback, pattern);
612                         retval = ERROR_FAIL;
613                         goto done;
614                 }
615                 ptr += wordsize;
616         }
617
618         if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) {
619                 command_print(CMD, "wrote %" PRIu32 " bytes to " TARGET_ADDR_FMT
620                         " in %fs (%0.3f KiB/s)", size_bytes, address,
621                         duration_elapsed(&bench), duration_kbps(&bench, size_bytes));
622         }
623
624 done:
625         free(buffer);
626
627         return retval;
628 }
629
630 COMMAND_HANDLER(handle_flash_md_command)
631 {
632         int retval;
633
634         if (CMD_ARGC < 1 || CMD_ARGC > 2)
635                 return ERROR_COMMAND_SYNTAX_ERROR;
636
637         target_addr_t address;
638         COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
639
640         uint32_t count = 1;
641         if (CMD_ARGC == 2)
642                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count);
643
644         unsigned int wordsize;
645         switch (CMD_NAME[2]) {
646                 case 'w':
647                         wordsize = 4;
648                         break;
649                 case 'h':
650                         wordsize = 2;
651                         break;
652                 case 'b':
653                         wordsize = 1;
654                         break;
655                 default:
656                         return ERROR_COMMAND_SYNTAX_ERROR;
657         }
658
659         if (count == 0)
660                 return ERROR_OK;
661
662         struct target *target = get_current_target(CMD_CTX);
663         struct flash_bank *bank;
664         retval = get_flash_bank_by_addr(target, address, true, &bank);
665         if (retval != ERROR_OK)
666                 return retval;
667
668         uint32_t offset = address - bank->base;
669         uint32_t sizebytes = count * wordsize;
670         if (offset + sizebytes > bank->size) {
671                 command_print(CMD, "Cannot cross flash bank borders");
672                 return ERROR_FAIL;
673         }
674
675         uint8_t *buffer = calloc(count, wordsize);
676         if (buffer == NULL) {
677                 command_print(CMD, "No memory for flash read buffer");
678                 return ERROR_FAIL;
679         }
680
681         retval = flash_driver_read(bank, buffer, offset, sizebytes);
682         if (retval == ERROR_OK)
683                 target_handle_md_output(CMD, target, address, wordsize, count, buffer);
684
685         free(buffer);
686
687         return retval;
688 }
689
690
691 COMMAND_HANDLER(handle_flash_write_bank_command)
692 {
693         uint32_t offset;
694         uint8_t *buffer;
695         size_t length;
696         struct fileio *fileio;
697
698         if (CMD_ARGC < 2 || CMD_ARGC > 3)
699                 return ERROR_COMMAND_SYNTAX_ERROR;
700
701         struct duration bench;
702         duration_start(&bench);
703
704         struct flash_bank *bank;
705         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
706         if (ERROR_OK != retval)
707                 return retval;
708
709         offset = 0;
710
711         if (CMD_ARGC > 2)
712                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
713
714         if (offset > bank->size) {
715                 LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
716                         offset);
717                 return ERROR_COMMAND_ARGUMENT_INVALID;
718         }
719
720         if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
721                 return ERROR_FAIL;
722
723         size_t filesize;
724         retval = fileio_size(fileio, &filesize);
725         if (retval != ERROR_OK) {
726                 fileio_close(fileio);
727                 return retval;
728         }
729
730         length = MIN(filesize, bank->size - offset);
731
732         if (!length) {
733                 LOG_INFO("Nothing to write to flash bank");
734                 fileio_close(fileio);
735                 return ERROR_OK;
736         }
737
738         if (length != filesize)
739                 LOG_INFO("File content exceeds flash bank size. Only writing the "
740                         "first %zu bytes of the file", length);
741
742         target_addr_t start_addr = bank->base + offset;
743         target_addr_t aligned_start = flash_write_align_start(bank, start_addr);
744         target_addr_t end_addr = start_addr + length - 1;
745         target_addr_t aligned_end = flash_write_align_end(bank, end_addr);
746         uint32_t aligned_size = aligned_end + 1 - aligned_start;
747         uint32_t padding_at_start = start_addr - aligned_start;
748         uint32_t padding_at_end = aligned_end - end_addr;
749
750         buffer = malloc(aligned_size);
751         if (buffer == NULL) {
752                 fileio_close(fileio);
753                 LOG_ERROR("Out of memory");
754                 return ERROR_FAIL;
755         }
756
757         if (padding_at_start) {
758                 memset(buffer, bank->default_padded_value, padding_at_start);
759                 LOG_WARNING("Start offset 0x%08" PRIx32
760                         " breaks the required alignment of flash bank %s",
761                         offset, bank->name);
762                 LOG_WARNING("Padding %" PRId32 " bytes from " TARGET_ADDR_FMT,
763                     padding_at_start, aligned_start);
764         }
765
766         uint8_t *ptr = buffer + padding_at_start;
767         size_t buf_cnt;
768         if (fileio_read(fileio, length, ptr, &buf_cnt) != ERROR_OK) {
769                 free(buffer);
770                 fileio_close(fileio);
771                 return ERROR_FAIL;
772         }
773
774         if (buf_cnt != length) {
775                 LOG_ERROR("Short read");
776                 free(buffer);
777                 return ERROR_FAIL;
778         }
779
780         ptr += length;
781
782         if (padding_at_end) {
783                 memset(ptr, bank->default_padded_value, padding_at_end);
784                 LOG_INFO("Padding at " TARGET_ADDR_FMT " with %" PRId32
785                         " bytes (bank write end alignment)",
786                         end_addr + 1, padding_at_end);
787         }
788
789         retval = flash_driver_write(bank, buffer, aligned_start - bank->base, aligned_size);
790
791         free(buffer);
792
793         if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
794                 command_print(CMD, "wrote %zu bytes from file %s to flash bank %u"
795                         " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
796                         length, CMD_ARGV[1], bank->bank_number, offset,
797                         duration_elapsed(&bench), duration_kbps(&bench, length));
798         }
799
800         fileio_close(fileio);
801
802         return retval;
803 }
804
805 COMMAND_HANDLER(handle_flash_read_bank_command)
806 {
807         uint32_t offset;
808         uint8_t *buffer;
809         struct fileio *fileio;
810         uint32_t length;
811         size_t written;
812
813         if (CMD_ARGC < 2 || CMD_ARGC > 4)
814                 return ERROR_COMMAND_SYNTAX_ERROR;
815
816         struct duration bench;
817         duration_start(&bench);
818
819         struct flash_bank *p;
820         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
821
822         if (ERROR_OK != retval)
823                 return retval;
824
825         offset = 0;
826
827         if (CMD_ARGC > 2)
828                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
829
830         if (offset > p->size) {
831                 LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
832                         offset);
833                 return ERROR_COMMAND_ARGUMENT_INVALID;
834         }
835
836         length = p->size - offset;
837
838         if (CMD_ARGC > 3)
839                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length);
840
841         if (offset + length > p->size) {
842                 LOG_ERROR("Length of %" PRIu32 " bytes with offset 0x%8.8" PRIx32
843                         " is out of range of the flash bank", length, offset);
844                 return ERROR_COMMAND_ARGUMENT_INVALID;
845         }
846
847         buffer = malloc(length);
848         if (buffer == NULL) {
849                 LOG_ERROR("Out of memory");
850                 return ERROR_FAIL;
851         }
852
853         retval = flash_driver_read(p, buffer, offset, length);
854         if (retval != ERROR_OK) {
855                 LOG_ERROR("Read error");
856                 free(buffer);
857                 return retval;
858         }
859
860         retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
861         if (retval != ERROR_OK) {
862                 LOG_ERROR("Could not open file");
863                 free(buffer);
864                 return retval;
865         }
866
867         retval = fileio_write(fileio, length, buffer, &written);
868         fileio_close(fileio);
869         free(buffer);
870         if (retval != ERROR_OK) {
871                 LOG_ERROR("Could not write file");
872                 return ERROR_FAIL;
873         }
874
875         if (duration_measure(&bench) == ERROR_OK)
876                 command_print(CMD, "wrote %zd bytes to file %s from flash bank %u"
877                         " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
878                         written, CMD_ARGV[1], p->bank_number, offset,
879                         duration_elapsed(&bench), duration_kbps(&bench, written));
880
881         return retval;
882 }
883
884
885 COMMAND_HANDLER(handle_flash_verify_bank_command)
886 {
887         uint32_t offset;
888         uint8_t *buffer_file, *buffer_flash;
889         struct fileio *fileio;
890         size_t read_cnt;
891         size_t filesize;
892         size_t length;
893         int differ;
894
895         if (CMD_ARGC < 2 || CMD_ARGC > 3)
896                 return ERROR_COMMAND_SYNTAX_ERROR;
897
898         struct duration bench;
899         duration_start(&bench);
900
901         struct flash_bank *p;
902         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
903         if (ERROR_OK != retval)
904                 return retval;
905
906         offset = 0;
907
908         if (CMD_ARGC > 2)
909                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
910
911         if (offset > p->size) {
912                 LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
913                         offset);
914                 return ERROR_COMMAND_ARGUMENT_INVALID;
915         }
916
917         retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
918         if (retval != ERROR_OK) {
919                 LOG_ERROR("Could not open file");
920                 return retval;
921         }
922
923         retval = fileio_size(fileio, &filesize);
924         if (retval != ERROR_OK) {
925                 fileio_close(fileio);
926                 return retval;
927         }
928
929         length = MIN(filesize, p->size - offset);
930
931         if (!length) {
932                 LOG_INFO("Nothing to compare with flash bank");
933                 fileio_close(fileio);
934                 return ERROR_OK;
935         }
936
937         if (length != filesize)
938                 LOG_INFO("File content exceeds flash bank size. Only comparing the "
939                         "first %zu bytes of the file", length);
940
941         buffer_file = malloc(length);
942         if (buffer_file == NULL) {
943                 LOG_ERROR("Out of memory");
944                 fileio_close(fileio);
945                 return ERROR_FAIL;
946         }
947
948         retval = fileio_read(fileio, length, buffer_file, &read_cnt);
949         fileio_close(fileio);
950         if (retval != ERROR_OK) {
951                 LOG_ERROR("File read failure");
952                 free(buffer_file);
953                 return retval;
954         }
955
956         if (read_cnt != length) {
957                 LOG_ERROR("Short read");
958                 free(buffer_file);
959                 return ERROR_FAIL;
960         }
961
962         buffer_flash = malloc(length);
963         if (buffer_flash == NULL) {
964                 LOG_ERROR("Out of memory");
965                 free(buffer_file);
966                 return ERROR_FAIL;
967         }
968
969         retval = flash_driver_read(p, buffer_flash, offset, length);
970         if (retval != ERROR_OK) {
971                 LOG_ERROR("Flash read error");
972                 free(buffer_flash);
973                 free(buffer_file);
974                 return retval;
975         }
976
977         if (duration_measure(&bench) == ERROR_OK)
978                 command_print(CMD, "read %zd bytes from file %s and flash bank %u"
979                         " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
980                         length, CMD_ARGV[1], p->bank_number, offset,
981                         duration_elapsed(&bench), duration_kbps(&bench, length));
982
983         differ = memcmp(buffer_file, buffer_flash, length);
984         command_print(CMD, "contents %s", differ ? "differ" : "match");
985         if (differ) {
986                 uint32_t t;
987                 int diffs = 0;
988                 for (t = 0; t < length; t++) {
989                         if (buffer_flash[t] == buffer_file[t])
990                                 continue;
991                         command_print(CMD, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x",
992                                         diffs, t + offset, buffer_flash[t], buffer_file[t]);
993                         if (diffs++ >= 127) {
994                                 command_print(CMD, "More than 128 errors, the rest are not printed.");
995                                 break;
996                         }
997                         keep_alive();
998                 }
999         }
1000         free(buffer_flash);
1001         free(buffer_file);
1002
1003         return differ ? ERROR_FAIL : ERROR_OK;
1004 }
1005
1006 void flash_set_dirty(void)
1007 {
1008         struct flash_bank *c;
1009
1010         /* set all flash to require erasing */
1011         for (c = flash_bank_list(); c; c = c->next) {
1012                 for (unsigned int i = 0; i < c->num_sectors; i++)
1013                         c->sectors[i].is_erased = 0;
1014         }
1015 }
1016
1017 COMMAND_HANDLER(handle_flash_padded_value_command)
1018 {
1019         if (CMD_ARGC != 2)
1020                 return ERROR_COMMAND_SYNTAX_ERROR;
1021
1022         struct flash_bank *p;
1023         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
1024         if (ERROR_OK != retval)
1025                 return retval;
1026
1027         COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value);
1028
1029         command_print(CMD, "Default padded value set to 0x%" PRIx8 " for flash bank %u",
1030                         p->default_padded_value, p->bank_number);
1031
1032         return retval;
1033 }
1034
1035 static const struct command_registration flash_exec_command_handlers[] = {
1036         {
1037                 .name = "probe",
1038                 .handler = handle_flash_probe_command,
1039                 .mode = COMMAND_EXEC,
1040                 .usage = "bank_id",
1041                 .help = "Identify a flash bank.",
1042         },
1043         {
1044                 .name = "info",
1045                 .handler = handle_flash_info_command,
1046                 .mode = COMMAND_EXEC,
1047                 .usage = "bank_id ['sectors']",
1048                 .help = "Print information about a flash bank.",
1049         },
1050         {
1051                 .name = "erase_check",
1052                 .handler = handle_flash_erase_check_command,
1053                 .mode = COMMAND_EXEC,
1054                 .usage = "bank_id",
1055                 .help = "Check erase state of all blocks in a "
1056                         "flash bank.",
1057         },
1058         {
1059                 .name = "erase_sector",
1060                 .handler = handle_flash_erase_command,
1061                 .mode = COMMAND_EXEC,
1062                 .usage = "bank_id first_sector_num (last_sector_num|'last')",
1063                 .help = "Erase a range of sectors in a flash bank.",
1064         },
1065         {
1066                 .name = "erase_address",
1067                 .handler = handle_flash_erase_address_command,
1068                 .mode = COMMAND_EXEC,
1069                 .usage = "['pad'] ['unlock'] address length",
1070                 .help = "Erase flash sectors starting at address and "
1071                         "continuing for length bytes.  If 'pad' is specified, "
1072                         "data outside that range may also be erased: the start "
1073                         "address may be decreased, and length increased, so "
1074                         "that all of the first and last sectors are erased. "
1075                         "If 'unlock' is specified, then the flash is unprotected "
1076                         "before erasing.",
1077
1078         },
1079         {
1080                 .name = "filld",
1081                 .handler = handle_flash_fill_command,
1082                 .mode = COMMAND_EXEC,
1083                 .usage = "address value n",
1084                 .help = "Fill n double-words with 64-bit value, starting at "
1085                         "word address.  (No autoerase.)",
1086         },
1087         {
1088                 .name = "fillw",
1089                 .handler = handle_flash_fill_command,
1090                 .mode = COMMAND_EXEC,
1091                 .usage = "address value n",
1092                 .help = "Fill n words with 32-bit value, starting at "
1093                         "word address.  (No autoerase.)",
1094         },
1095         {
1096                 .name = "fillh",
1097                 .handler = handle_flash_fill_command,
1098                 .mode = COMMAND_EXEC,
1099                 .usage = "address value n",
1100                 .help = "Fill n halfwords with 16-bit value, starting at "
1101                         "word address.  (No autoerase.)",
1102         },
1103         {
1104                 .name = "fillb",
1105                 .handler = handle_flash_fill_command,
1106                 .mode = COMMAND_EXEC,
1107                 .usage = "address value n",
1108                 .help = "Fill n bytes with 8-bit value, starting at "
1109                         "word address.  (No autoerase.)",
1110         },
1111         {
1112                 .name = "mdb",
1113                 .handler = handle_flash_md_command,
1114                 .mode = COMMAND_EXEC,
1115                 .usage = "address [count]",
1116                 .help = "Display bytes from flash.",
1117         },
1118         {
1119                 .name = "mdh",
1120                 .handler = handle_flash_md_command,
1121                 .mode = COMMAND_EXEC,
1122                 .usage = "address [count]",
1123                 .help = "Display half-words from flash.",
1124         },
1125         {
1126                 .name = "mdw",
1127                 .handler = handle_flash_md_command,
1128                 .mode = COMMAND_EXEC,
1129                 .usage = "address [count]",
1130                 .help = "Display words from flash.",
1131         },
1132         {
1133                 .name = "write_bank",
1134                 .handler = handle_flash_write_bank_command,
1135                 .mode = COMMAND_EXEC,
1136                 .usage = "bank_id filename [offset]",
1137                 .help = "Write binary data from file to flash bank. Allow optional "
1138                         "offset from beginning of the bank (defaults to zero).",
1139         },
1140         {
1141                 .name = "write_image",
1142                 .handler = handle_flash_write_image_command,
1143                 .mode = COMMAND_EXEC,
1144                 .usage = "[erase] [unlock] filename [offset [file_type]]",
1145                 .help = "Write an image to flash.  Optionally first unprotect "
1146                         "and/or erase the region to be used.  Allow optional "
1147                         "offset from beginning of bank (defaults to zero)",
1148         },
1149         {
1150                 .name = "read_bank",
1151                 .handler = handle_flash_read_bank_command,
1152                 .mode = COMMAND_EXEC,
1153                 .usage = "bank_id filename [offset [length]]",
1154                 .help = "Read binary data from flash bank to file. Allow optional "
1155                         "offset from beginning of the bank (defaults to zero).",
1156         },
1157         {
1158                 .name = "verify_bank",
1159                 .handler = handle_flash_verify_bank_command,
1160                 .mode = COMMAND_EXEC,
1161                 .usage = "bank_id filename [offset]",
1162                 .help = "Compare the contents of a file with the contents of the "
1163                         "flash bank. Allow optional offset from beginning of the bank "
1164                         "(defaults to zero).",
1165         },
1166         {
1167                 .name = "protect",
1168                 .handler = handle_flash_protect_command,
1169                 .mode = COMMAND_EXEC,
1170                 .usage = "bank_id first_block [last_block|'last'] "
1171                         "('on'|'off')",
1172                 .help = "Turn protection on or off for a range of protection "
1173                         "blocks or sectors in a given flash bank. "
1174                         "See 'flash info' output for a list of blocks.",
1175         },
1176         {
1177                 .name = "padded_value",
1178                 .handler = handle_flash_padded_value_command,
1179                 .mode = COMMAND_EXEC,
1180                 .usage = "bank_id value",
1181                 .help = "Set default flash padded value",
1182         },
1183         COMMAND_REGISTRATION_DONE
1184 };
1185
1186 static int flash_init_drivers(struct command_context *cmd_ctx)
1187 {
1188         if (!flash_bank_list())
1189                 return ERROR_OK;
1190
1191         struct command *parent = command_find_in_context(cmd_ctx, "flash");
1192         return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
1193 }
1194
1195 COMMAND_HANDLER(handle_flash_bank_command)
1196 {
1197         if (CMD_ARGC < 7) {
1198                 LOG_ERROR("usage: flash bank <name> <driver> "
1199                         "<base> <size> <chip_width> <bus_width> <target>");
1200                 return ERROR_COMMAND_SYNTAX_ERROR;
1201         }
1202         /* save bank name and advance arguments for compatibility */
1203         const char *bank_name = *CMD_ARGV++;
1204         CMD_ARGC--;
1205
1206         struct target *target = get_target(CMD_ARGV[5]);
1207         if (target == NULL) {
1208                 LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
1209                 return ERROR_FAIL;
1210         }
1211
1212         const char *driver_name = CMD_ARGV[0];
1213         const struct flash_driver *driver = flash_driver_find_by_name(driver_name);
1214         if (NULL == driver) {
1215                 /* no matching flash driver found */
1216                 LOG_ERROR("flash driver '%s' not found", driver_name);
1217                 return ERROR_FAIL;
1218         }
1219
1220         /* check the flash bank name is unique */
1221         if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
1222                 /* flash bank name already exists  */
1223                 LOG_ERROR("flash bank name '%s' already exists", bank_name);
1224                 return ERROR_FAIL;
1225         }
1226
1227         /* register flash specific commands */
1228         if (NULL != driver->commands) {
1229                 int retval = register_commands(CMD_CTX, NULL,
1230                                 driver->commands);
1231                 if (ERROR_OK != retval) {
1232                         LOG_ERROR("couldn't register '%s' commands",
1233                                 driver_name);
1234                         return ERROR_FAIL;
1235                 }
1236         }
1237
1238         struct flash_bank *c = calloc(1, sizeof(*c));
1239         c->name = strdup(bank_name);
1240         c->target = target;
1241         c->driver = driver;
1242         COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[1], c->base);
1243         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
1244         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[3], c->chip_width);
1245         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[4], c->bus_width);
1246         c->default_padded_value = c->erased_value = 0xff;
1247         c->minimal_write_gap = FLASH_WRITE_GAP_SECTOR;
1248
1249         int retval;
1250         retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
1251         if (ERROR_OK != retval) {
1252                 LOG_ERROR("'%s' driver rejected flash bank at " TARGET_ADDR_FMT
1253                                 "; usage: %s", driver_name, c->base, driver->usage);
1254                 free(c);
1255                 return retval;
1256         }
1257
1258         if (driver->usage == NULL)
1259                 LOG_DEBUG("'%s' driver usage field missing", driver_name);
1260
1261         flash_bank_add(c);
1262
1263         return ERROR_OK;
1264 }
1265
1266 COMMAND_HANDLER(handle_flash_banks_command)
1267 {
1268         if (CMD_ARGC != 0)
1269                 return ERROR_COMMAND_SYNTAX_ERROR;
1270
1271         unsigned n = 0;
1272         for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
1273                 command_print(CMD, "#%d : %s (%s) at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32 ", "
1274                         "buswidth %u, chipwidth %u", p->bank_number,
1275                         p->name, p->driver->name, p->base, p->size,
1276                         p->bus_width, p->chip_width);
1277         }
1278         return ERROR_OK;
1279 }
1280
1281 static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
1282 {
1283         if (argc != 1) {
1284                 Jim_WrongNumArgs(interp, 1, argv,
1285                         "no arguments to 'flash list' command");
1286                 return JIM_ERR;
1287         }
1288
1289         Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
1290
1291         for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
1292                 Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
1293
1294                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
1295                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
1296                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
1297                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
1298                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
1299                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
1300                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
1301                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
1302                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
1303                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
1304
1305                 Jim_ListAppendElement(interp, list, elem);
1306         }
1307
1308         Jim_SetResult(interp, list);
1309
1310         return JIM_OK;
1311 }
1312
1313 COMMAND_HANDLER(handle_flash_init_command)
1314 {
1315         if (CMD_ARGC != 0)
1316                 return ERROR_COMMAND_SYNTAX_ERROR;
1317
1318         static bool flash_initialized;
1319         if (flash_initialized) {
1320                 LOG_INFO("'flash init' has already been called");
1321                 return ERROR_OK;
1322         }
1323         flash_initialized = true;
1324
1325         LOG_DEBUG("Initializing flash devices...");
1326         return flash_init_drivers(CMD_CTX);
1327 }
1328
1329 static const struct command_registration flash_config_command_handlers[] = {
1330         {
1331                 .name = "bank",
1332                 .handler = handle_flash_bank_command,
1333                 .mode = COMMAND_CONFIG,
1334                 .usage = "bank_id driver_name base_address size_bytes "
1335                         "chip_width_bytes bus_width_bytes target "
1336                         "[driver_options ...]",
1337                 .help = "Define a new bank with the given name, "
1338                         "using the specified NOR flash driver.",
1339         },
1340         {
1341                 .name = "init",
1342                 .mode = COMMAND_CONFIG,
1343                 .handler = handle_flash_init_command,
1344                 .help = "Initialize flash devices.",
1345                 .usage = "",
1346         },
1347         {
1348                 .name = "banks",
1349                 .mode = COMMAND_ANY,
1350                 .handler = handle_flash_banks_command,
1351                 .help = "Display table with information about flash banks.",
1352                 .usage = "",
1353         },
1354         {
1355                 .name = "list",
1356                 .mode = COMMAND_ANY,
1357                 .jim_handler = jim_flash_list,
1358                 .help = "Returns a list of details about the flash banks.",
1359         },
1360         COMMAND_REGISTRATION_DONE
1361 };
1362 static const struct command_registration flash_command_handlers[] = {
1363         {
1364                 .name = "flash",
1365                 .mode = COMMAND_ANY,
1366                 .help = "NOR flash command group",
1367                 .chain = flash_config_command_handlers,
1368                 .usage = "",
1369         },
1370         COMMAND_REGISTRATION_DONE
1371 };
1372
1373 int flash_register_commands(struct command_context *cmd_ctx)
1374 {
1375         return register_commands(cmd_ctx, NULL, flash_command_handlers);
1376 }