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

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)