flash/nor/tcl: fix segfault on write_image misuse
[openocd.git] / 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 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "imp.h"
26 #include <helper/time_support.h>
27 #include <target/image.h>
28
29 /**
30 * @file
31 * Implements Tcl commands used to access NOR flash facilities.
32 */
33
34 COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
35 struct flash_bank **bank)
36 {
37 const char *name = CMD_ARGV[name_index];
38 int retval = get_flash_bank_by_name(name, bank);
39 if (retval != ERROR_OK)
40 return retval;
41 if (*bank)
42 return ERROR_OK;
43
44 unsigned bank_num;
45 COMMAND_PARSE_NUMBER(uint, name, bank_num);
46
47 return get_flash_bank_by_num(bank_num, bank);
48 }
49
50 COMMAND_HANDLER(handle_flash_info_command)
51 {
52 struct flash_bank *p;
53 int j = 0;
54 int retval;
55
56 if (CMD_ARGC != 1)
57 return ERROR_COMMAND_SYNTAX_ERROR;
58
59 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
60 if (retval != ERROR_OK)
61 return retval;
62
63 if (p != NULL) {
64 char buf[1024];
65
66 /* attempt auto probe */
67 retval = p->driver->auto_probe(p);
68 if (retval != ERROR_OK)
69 return retval;
70
71 /* We must query the hardware to avoid printing stale information! */
72 retval = p->driver->protect_check(p);
73 if (retval != ERROR_OK)
74 return retval;
75
76 command_print(CMD_CTX,
77 "#%d : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32
78 ", buswidth %i, chipwidth %i",
79 p->bank_number,
80 p->driver->name,
81 p->base,
82 p->size,
83 p->bus_width,
84 p->chip_width);
85 for (j = 0; j < p->num_sectors; j++) {
86 char *protect_state;
87
88 if (p->sectors[j].is_protected == 0)
89 protect_state = "not protected";
90 else if (p->sectors[j].is_protected == 1)
91 protect_state = "protected";
92 else
93 protect_state = "protection state unknown";
94
95 command_print(CMD_CTX,
96 "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
97 j,
98 p->sectors[j].offset,
99 p->sectors[j].size,
100 p->sectors[j].size >> 10,
101 protect_state);
102 }
103
104 if (p->driver->info != NULL) {
105 retval = p->driver->info(p, buf, sizeof(buf));
106 if (retval == ERROR_OK)
107 command_print(CMD_CTX, "%s", buf);
108 else
109 LOG_ERROR("error retrieving flash info");
110 }
111 }
112
113 return retval;
114 }
115
116 COMMAND_HANDLER(handle_flash_probe_command)
117 {
118 struct flash_bank *p;
119 int retval;
120
121 if (CMD_ARGC != 1)
122 return ERROR_COMMAND_SYNTAX_ERROR;
123
124 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
125 if (retval != ERROR_OK)
126 return retval;
127
128 if (p) {
129 retval = p->driver->probe(p);
130 if (retval == ERROR_OK)
131 command_print(CMD_CTX,
132 "flash '%s' found at 0x%8.8" PRIx32,
133 p->driver->name,
134 p->base);
135 } else {
136 command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
137 retval = ERROR_FAIL;
138 }
139
140 return retval;
141 }
142
143 COMMAND_HANDLER(handle_flash_erase_check_command)
144 {
145 if (CMD_ARGC != 1)
146 return ERROR_COMMAND_SYNTAX_ERROR;
147
148 struct flash_bank *p;
149 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
150 if (ERROR_OK != retval)
151 return retval;
152
153 int j;
154 retval = p->driver->erase_check(p);
155 if (retval == ERROR_OK)
156 command_print(CMD_CTX, "successfully checked erase state");
157 else {
158 command_print(CMD_CTX,
159 "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
160 CMD_ARGV[0],
161 p->base);
162 }
163
164 for (j = 0; j < p->num_sectors; j++) {
165 char *erase_state;
166
167 if (p->sectors[j].is_erased == 0)
168 erase_state = "not erased";
169 else if (p->sectors[j].is_erased == 1)
170 erase_state = "erased";
171 else
172 erase_state = "erase state unknown";
173
174 command_print(CMD_CTX,
175 "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
176 j,
177 p->sectors[j].offset,
178 p->sectors[j].size,
179 p->sectors[j].size >> 10,
180 erase_state);
181 }
182
183 return retval;
184 }
185
186 COMMAND_HANDLER(handle_flash_erase_address_command)
187 {
188 struct flash_bank *p;
189 int retval = ERROR_OK;
190 uint32_t address;
191 uint32_t length;
192 bool do_pad = false;
193 bool do_unlock = false;
194 struct target *target = get_current_target(CMD_CTX);
195
196 while (CMD_ARGC >= 3) {
197 /* Optionally pad out the address range to block/sector
198 * boundaries. We can't know if there's data in that part
199 * of the flash; only do padding if we're told to.
200 */
201 if (strcmp("pad", CMD_ARGV[0]) == 0)
202 do_pad = true;
203 else if (strcmp("unlock", CMD_ARGV[0]) == 0)
204 do_unlock = true;
205 else
206 return ERROR_COMMAND_SYNTAX_ERROR;
207 CMD_ARGC--;
208 CMD_ARGV++;
209 }
210 if (CMD_ARGC != 2)
211 return ERROR_COMMAND_SYNTAX_ERROR;
212
213 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
214 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
215
216 if (length <= 0) {
217 command_print(CMD_CTX, "Length must be >0");
218 return ERROR_COMMAND_SYNTAX_ERROR;
219 }
220
221 retval = get_flash_bank_by_addr(target, address, true, &p);
222 if (retval != ERROR_OK)
223 return retval;
224
225 /* We can't know if we did a resume + halt, in which case we no longer know the erased state
226 **/
227 flash_set_dirty();
228
229 struct duration bench;
230 duration_start(&bench);
231
232 if (do_unlock)
233 retval = flash_unlock_address_range(target, address, length);
234
235 if (retval == ERROR_OK)
236 retval = flash_erase_address_range(target, do_pad, address, length);
237
238 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
239 command_print(CMD_CTX, "erased address 0x%8.8" PRIx32 " (length %" PRIi32 ")"
240 " in %fs (%0.3f KiB/s)", address, length,
241 duration_elapsed(&bench), duration_kbps(&bench, length));
242 }
243
244 return retval;
245 }
246
247 static int flash_check_sector_parameters(struct command_context *cmd_ctx,
248 uint32_t first, uint32_t last, uint32_t num_sectors)
249 {
250 if (!(first <= last)) {
251 command_print(cmd_ctx, "ERROR: "
252 "first sector must be <= last sector");
253 return ERROR_FAIL;
254 }
255
256 if (!(last <= (num_sectors - 1))) {
257 command_print(cmd_ctx, "ERROR: last sector must be <= %d",
258 (int) num_sectors - 1);
259 return ERROR_FAIL;
260 }
261
262 return ERROR_OK;
263 }
264
265 COMMAND_HANDLER(handle_flash_erase_command)
266 {
267 if (CMD_ARGC != 3)
268 return ERROR_COMMAND_SYNTAX_ERROR;
269
270 uint32_t first;
271 uint32_t last;
272
273 struct flash_bank *p;
274 int retval;
275
276 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
277 if (retval != ERROR_OK)
278 return retval;
279
280 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
281 if (strcmp(CMD_ARGV[2], "last") == 0)
282 last = p->num_sectors - 1;
283 else
284 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
285
286 retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
287 if (retval != ERROR_OK)
288 return retval;
289
290 struct duration bench;
291 duration_start(&bench);
292
293 retval = flash_driver_erase(p, first, last);
294
295 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
296 command_print(CMD_CTX, "erased sectors %" PRIu32 " "
297 "through %" PRIu32 " on flash bank %d "
298 "in %fs", first, last, p->bank_number, duration_elapsed(&bench));
299 }
300
301 return ERROR_OK;
302 }
303
304 COMMAND_HANDLER(handle_flash_protect_command)
305 {
306 if (CMD_ARGC != 4)
307 return ERROR_COMMAND_SYNTAX_ERROR;
308
309 uint32_t first;
310 uint32_t last;
311
312 struct flash_bank *p;
313 int retval;
314
315 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
316 if (retval != ERROR_OK)
317 return retval;
318
319 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
320 if (strcmp(CMD_ARGV[2], "last") == 0)
321 last = p->num_sectors - 1;
322 else
323 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
324
325 bool set;
326 COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
327
328 retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
329 if (retval != ERROR_OK)
330 return retval;
331
332 retval = flash_driver_protect(p, set, first, last);
333 if (retval == ERROR_OK) {
334 command_print(CMD_CTX, "%s protection for sectors %i "
335 "through %i on flash bank %d",
336 (set) ? "set" : "cleared", (int) first,
337 (int) last, p->bank_number);
338 }
339
340 return retval;
341 }
342
343 COMMAND_HANDLER(handle_flash_write_image_command)
344 {
345 struct target *target = get_current_target(CMD_CTX);
346
347 struct image image;
348 uint32_t written;
349
350 int retval;
351
352 /* flash auto-erase is disabled by default*/
353 int auto_erase = 0;
354 bool auto_unlock = false;
355
356 while (CMD_ARGC) {
357 if (strcmp(CMD_ARGV[0], "erase") == 0) {
358 auto_erase = 1;
359 CMD_ARGV++;
360 CMD_ARGC--;
361 command_print(CMD_CTX, "auto erase enabled");
362 } else if (strcmp(CMD_ARGV[0], "unlock") == 0) {
363 auto_unlock = true;
364 CMD_ARGV++;
365 CMD_ARGC--;
366 command_print(CMD_CTX, "auto unlock enabled");
367 } else
368 break;
369 }
370
371 if (CMD_ARGC < 1)
372 return ERROR_COMMAND_SYNTAX_ERROR;
373
374 if (!target) {
375 LOG_ERROR("no target selected");
376 return ERROR_FAIL;
377 }
378
379 struct duration bench;
380 duration_start(&bench);
381
382 if (CMD_ARGC >= 2) {
383 image.base_address_set = 1;
384 COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
385 } else {
386 image.base_address_set = 0;
387 image.base_address = 0x0;
388 }
389
390 image.start_address_set = 0;
391
392 retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
393 if (retval != ERROR_OK)
394 return retval;
395
396 retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
397 if (retval != ERROR_OK) {
398 image_close(&image);
399 return retval;
400 }
401
402 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
403 command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
404 "in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
405 duration_elapsed(&bench), duration_kbps(&bench, written));
406 }
407
408 image_close(&image);
409
410 return retval;
411 }
412
413 COMMAND_HANDLER(handle_flash_fill_command)
414 {
415 int err = ERROR_OK;
416 uint32_t address;
417 uint32_t pattern;
418 uint32_t count;
419 uint32_t wrote = 0;
420 uint32_t cur_size = 0;
421 uint32_t chunk_count;
422 struct target *target = get_current_target(CMD_CTX);
423 unsigned i;
424 uint32_t wordsize;
425 int retval = ERROR_OK;
426
427 static size_t const chunksize = 1024;
428 uint8_t *chunk = NULL, *readback = NULL;
429
430 if (CMD_ARGC != 3) {
431 retval = ERROR_COMMAND_SYNTAX_ERROR;
432 goto done;
433 }
434
435 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
436 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
437 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
438
439 chunk = malloc(chunksize);
440 if (chunk == NULL)
441 return ERROR_FAIL;
442
443 readback = malloc(chunksize);
444 if (readback == NULL) {
445 free(chunk);
446 return ERROR_FAIL;
447 }
448
449 if (count == 0)
450 goto done;
451
452 switch (CMD_NAME[4]) {
453 case 'w':
454 wordsize = 4;
455 break;
456 case 'h':
457 wordsize = 2;
458 break;
459 case 'b':
460 wordsize = 1;
461 break;
462 default:
463 retval = ERROR_COMMAND_SYNTAX_ERROR;
464 goto done;
465 }
466
467 chunk_count = MIN(count, (chunksize / wordsize));
468 switch (wordsize) {
469 case 4:
470 for (i = 0; i < chunk_count; i++)
471 target_buffer_set_u32(target, chunk + i * wordsize, pattern);
472 break;
473 case 2:
474 for (i = 0; i < chunk_count; i++)
475 target_buffer_set_u16(target, chunk + i * wordsize, pattern);
476 break;
477 case 1:
478 memset(chunk, pattern, chunk_count);
479 break;
480 default:
481 LOG_ERROR("BUG: can't happen");
482 exit(-1);
483 }
484
485 struct duration bench;
486 duration_start(&bench);
487
488 for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) {
489 struct flash_bank *bank;
490
491 retval = get_flash_bank_by_addr(target, address, true, &bank);
492 if (retval != ERROR_OK)
493 goto done;
494
495 cur_size = MIN((count * wordsize - wrote), chunksize);
496 err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
497 if (err != ERROR_OK) {
498 retval = err;
499 goto done;
500 }
501
502 err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size);
503 if (err != ERROR_OK) {
504 retval = err;
505 goto done;
506 }
507
508 for (i = 0; i < cur_size; i++) {
509 if (readback[i] != chunk[i]) {
510 LOG_ERROR(
511 "Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
512 address + wrote + i,
513 readback[i],
514 chunk[i]);
515 retval = ERROR_FAIL;
516 goto done;
517 }
518 }
519 }
520
521 if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) {
522 command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
523 " in %fs (%0.3f KiB/s)", wrote, address,
524 duration_elapsed(&bench), duration_kbps(&bench, wrote));
525 }
526
527 done:
528 free(readback);
529 free(chunk);
530
531 return retval;
532 }
533
534 COMMAND_HANDLER(handle_flash_write_bank_command)
535 {
536 uint32_t offset;
537 uint8_t *buffer;
538 struct fileio fileio;
539
540 if (CMD_ARGC != 3)
541 return ERROR_COMMAND_SYNTAX_ERROR;
542
543 struct duration bench;
544 duration_start(&bench);
545
546 struct flash_bank *p;
547 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
548 if (ERROR_OK != retval)
549 return retval;
550
551 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
552
553 if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
554 return ERROR_OK;
555
556 int filesize;
557 retval = fileio_size(&fileio, &filesize);
558 if (retval != ERROR_OK) {
559 fileio_close(&fileio);
560 return retval;
561 }
562
563 buffer = malloc(filesize);
564 if (buffer == NULL) {
565 fileio_close(&fileio);
566 LOG_ERROR("Out of memory");
567 return ERROR_FAIL;
568 }
569 size_t buf_cnt;
570 if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
571 free(buffer);
572 fileio_close(&fileio);
573 return ERROR_OK;
574 }
575
576 retval = flash_driver_write(p, buffer, offset, buf_cnt);
577
578 free(buffer);
579 buffer = NULL;
580
581 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
582 command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
583 " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
584 (long)filesize, CMD_ARGV[1], p->bank_number, offset,
585 duration_elapsed(&bench), duration_kbps(&bench, filesize));
586 }
587
588 fileio_close(&fileio);
589
590 return retval;
591 }
592
593 void flash_set_dirty(void)
594 {
595 struct flash_bank *c;
596 int i;
597
598 /* set all flash to require erasing */
599 for (c = flash_bank_list(); c; c = c->next) {
600 for (i = 0; i < c->num_sectors; i++)
601 c->sectors[i].is_erased = 0;
602 }
603 }
604
605 COMMAND_HANDLER(handle_flash_padded_value_command)
606 {
607 if (CMD_ARGC != 2)
608 return ERROR_COMMAND_SYNTAX_ERROR;
609
610 struct flash_bank *p;
611 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
612 if (ERROR_OK != retval)
613 return retval;
614
615 COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value);
616
617 command_print(CMD_CTX, "Default padded value set to 0x%" PRIx8 " for flash bank %u", \
618 p->default_padded_value, p->bank_number);
619
620 return retval;
621 }
622
623 static const struct command_registration flash_exec_command_handlers[] = {
624 {
625 .name = "probe",
626 .handler = handle_flash_probe_command,
627 .mode = COMMAND_EXEC,
628 .usage = "bank_id",
629 .help = "Identify a flash bank.",
630 },
631 {
632 .name = "info",
633 .handler = handle_flash_info_command,
634 .mode = COMMAND_EXEC,
635 .usage = "bank_id",
636 .help = "Print information about a flash bank.",
637 },
638 {
639 .name = "erase_check",
640 .handler = handle_flash_erase_check_command,
641 .mode = COMMAND_EXEC,
642 .usage = "bank_id",
643 .help = "Check erase state of all blocks in a "
644 "flash bank.",
645 },
646 {
647 .name = "erase_sector",
648 .handler = handle_flash_erase_command,
649 .mode = COMMAND_EXEC,
650 .usage = "bank_id first_sector_num last_sector_num",
651 .help = "Erase a range of sectors in a flash bank.",
652 },
653 {
654 .name = "erase_address",
655 .handler = handle_flash_erase_address_command,
656 .mode = COMMAND_EXEC,
657 .usage = "['pad'] ['unlock'] address length",
658 .help = "Erase flash sectors starting at address and "
659 "continuing for length bytes. If 'pad' is specified, "
660 "data outside that range may also be erased: the start "
661 "address may be decreased, and length increased, so "
662 "that all of the first and last sectors are erased. "
663 "If 'unlock' is specified, then the flash is unprotected "
664 "before erasing.",
665
666 },
667 {
668 .name = "fillw",
669 .handler = handle_flash_fill_command,
670 .mode = COMMAND_EXEC,
671 .usage = "address value n",
672 .help = "Fill n words with 32-bit value, starting at "
673 "word address. (No autoerase.)",
674 },
675 {
676 .name = "fillh",
677 .handler = handle_flash_fill_command,
678 .mode = COMMAND_EXEC,
679 .usage = "address value n",
680 .help = "Fill n halfwords with 16-bit value, starting at "
681 "word address. (No autoerase.)",
682 },
683 {
684 .name = "fillb",
685 .handler = handle_flash_fill_command,
686 .mode = COMMAND_EXEC,
687 .usage = "address value n",
688 .help = "Fill n bytes with 8-bit value, starting at "
689 "word address. (No autoerase.)",
690 },
691 {
692 .name = "write_bank",
693 .handler = handle_flash_write_bank_command,
694 .mode = COMMAND_EXEC,
695 .usage = "bank_id filename offset",
696 .help = "Write binary data from file to flash bank, "
697 "starting at specified byte offset from the "
698 "beginning of the bank.",
699 },
700 {
701 .name = "write_image",
702 .handler = handle_flash_write_image_command,
703 .mode = COMMAND_EXEC,
704 .usage = "[erase] [unlock] filename [offset [file_type]]",
705 .help = "Write an image to flash. Optionally first unprotect "
706 "and/or erase the region to be used. Allow optional "
707 "offset from beginning of bank (defaults to zero)",
708 },
709 {
710 .name = "protect",
711 .handler = handle_flash_protect_command,
712 .mode = COMMAND_EXEC,
713 .usage = "bank_id first_sector [last_sector|'last'] "
714 "('on'|'off')",
715 .help = "Turn protection on or off for a range of sectors "
716 "in a given flash bank.",
717 },
718 {
719 .name = "padded_value",
720 .handler = handle_flash_padded_value_command,
721 .mode = COMMAND_EXEC,
722 .usage = "bank_id value",
723 .help = "Set default flash padded value",
724 },
725 COMMAND_REGISTRATION_DONE
726 };
727
728 static int flash_init_drivers(struct command_context *cmd_ctx)
729 {
730 if (!flash_bank_list())
731 return ERROR_OK;
732
733 struct command *parent = command_find_in_context(cmd_ctx, "flash");
734 return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
735 }
736
737 COMMAND_HANDLER(handle_flash_bank_command)
738 {
739 if (CMD_ARGC < 7) {
740 LOG_ERROR("usage: flash bank <name> <driver> "
741 "<base> <size> <chip_width> <bus_width> <target>");
742 return ERROR_COMMAND_SYNTAX_ERROR;
743 }
744 /* save bank name and advance arguments for compatibility */
745 const char *bank_name = *CMD_ARGV++;
746 CMD_ARGC--;
747
748 struct target *target = get_target(CMD_ARGV[5]);
749 if (target == NULL) {
750 LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
751 return ERROR_FAIL;
752 }
753
754 const char *driver_name = CMD_ARGV[0];
755 struct flash_driver *driver = flash_driver_find_by_name(driver_name);
756 if (NULL == driver) {
757 /* no matching flash driver found */
758 LOG_ERROR("flash driver '%s' not found", driver_name);
759 return ERROR_FAIL;
760 }
761
762 /* check the flash bank name is unique */
763 if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
764 /* flash bank name already exists */
765 LOG_ERROR("flash bank name '%s' already exists", bank_name);
766 return ERROR_FAIL;
767 }
768
769 /* register flash specific commands */
770 if (NULL != driver->commands) {
771 int retval = register_commands(CMD_CTX, NULL,
772 driver->commands);
773 if (ERROR_OK != retval) {
774 LOG_ERROR("couldn't register '%s' commands",
775 driver_name);
776 return ERROR_FAIL;
777 }
778 }
779
780 struct flash_bank *c = malloc(sizeof(*c));
781 c->name = strdup(bank_name);
782 c->target = target;
783 c->driver = driver;
784 c->driver_priv = NULL;
785 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base);
786 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
787 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
788 COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
789 c->default_padded_value = 0xff;
790 c->num_sectors = 0;
791 c->sectors = NULL;
792 c->next = NULL;
793
794 int retval;
795 retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
796 if (ERROR_OK != retval) {
797 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "Usage %s",
798 driver_name, c->base, driver->usage);
799 free(c);
800 return retval;
801 }
802
803 if (driver->usage == NULL)
804 LOG_DEBUG("'%s' driver usage field missing", driver_name);
805
806 flash_bank_add(c);
807
808 return ERROR_OK;
809 }
810
811 COMMAND_HANDLER(handle_flash_banks_command)
812 {
813 if (CMD_ARGC != 0)
814 return ERROR_COMMAND_SYNTAX_ERROR;
815
816 unsigned n = 0;
817 for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
818 LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
819 "buswidth %u, chipwidth %u", p->bank_number,
820 p->name, p->driver->name, p->base, p->size,
821 p->bus_width, p->chip_width);
822 }
823 return ERROR_OK;
824 }
825
826 static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
827 {
828 if (argc != 1) {
829 Jim_WrongNumArgs(interp, 1, argv,
830 "no arguments to 'flash list' command");
831 return JIM_ERR;
832 }
833
834 Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
835
836 for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
837 Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
838
839 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
840 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
841 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
842 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
843 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
844 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
845 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
846 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
847 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
848 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
849
850 Jim_ListAppendElement(interp, list, elem);
851 }
852
853 Jim_SetResult(interp, list);
854
855 return JIM_OK;
856 }
857
858 COMMAND_HANDLER(handle_flash_init_command)
859 {
860 if (CMD_ARGC != 0)
861 return ERROR_COMMAND_SYNTAX_ERROR;
862
863 static bool flash_initialized;
864 if (flash_initialized) {
865 LOG_INFO("'flash init' has already been called");
866 return ERROR_OK;
867 }
868 flash_initialized = true;
869
870 LOG_DEBUG("Initializing flash devices...");
871 return flash_init_drivers(CMD_CTX);
872 }
873
874 static const struct command_registration flash_config_command_handlers[] = {
875 {
876 .name = "bank",
877 .handler = handle_flash_bank_command,
878 .mode = COMMAND_CONFIG,
879 .usage = "bank_id driver_name base_address size_bytes "
880 "chip_width_bytes bus_width_bytes target "
881 "[driver_options ...]",
882 .help = "Define a new bank with the given name, "
883 "using the specified NOR flash driver.",
884 },
885 {
886 .name = "init",
887 .mode = COMMAND_CONFIG,
888 .handler = handle_flash_init_command,
889 .help = "Initialize flash devices.",
890 },
891 {
892 .name = "banks",
893 .mode = COMMAND_ANY,
894 .handler = handle_flash_banks_command,
895 .help = "Display table with information about flash banks.",
896 },
897 {
898 .name = "list",
899 .mode = COMMAND_ANY,
900 .jim_handler = jim_flash_list,
901 .help = "Returns a list of details about the flash banks.",
902 },
903 COMMAND_REGISTRATION_DONE
904 };
905 static const struct command_registration flash_command_handlers[] = {
906 {
907 .name = "flash",
908 .mode = COMMAND_ANY,
909 .help = "NOR flash command group",
910 .chain = flash_config_command_handlers,
911 },
912 COMMAND_REGISTRATION_DONE
913 };
914
915 int flash_register_commands(struct command_context *cmd_ctx)
916 {
917 return register_commands(cmd_ctx, NULL, flash_command_handlers);
918 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)