1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
27 #include "time_support.h"
35 #include <sys/types.h>
40 /* command handlers */
41 int handle_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
42 int handle_flash_banks_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
43 int handle_flash_info_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
44 int handle_flash_probe_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
45 int handle_flash_erase_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
46 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
47 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
48 int handle_flash_write_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
49 int handle_flash_write_binary_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
50 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
51 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
55 extern flash_driver_t lpc2000_flash
;
56 extern flash_driver_t cfi_flash
;
57 extern flash_driver_t at91sam7_flash
;
58 extern flash_driver_t str7x_flash
;
59 extern flash_driver_t str9x_flash
;
60 extern flash_driver_t stellaris_flash
;
61 extern flash_driver_t str9xpec_flash
;
62 extern flash_driver_t stm32x_flash
;
64 flash_driver_t
*flash_drivers
[] =
77 flash_bank_t
*flash_banks
;
78 static command_t
*flash_cmd
;
80 int flash_register_commands(struct command_context_s
*cmd_ctx
)
82 flash_cmd
= register_command(cmd_ctx
, NULL
, "flash", NULL
, COMMAND_ANY
, NULL
);
84 register_command(cmd_ctx
, flash_cmd
, "bank", handle_flash_bank_command
, COMMAND_CONFIG
, NULL
);
89 int flash_init(struct command_context_s
*cmd_ctx
)
93 register_command(cmd_ctx
, flash_cmd
, "banks", handle_flash_banks_command
, COMMAND_EXEC
,
94 "list configured flash banks ");
95 register_command(cmd_ctx
, flash_cmd
, "info", handle_flash_info_command
, COMMAND_EXEC
,
96 "print info about flash bank <num>");
97 register_command(cmd_ctx
, flash_cmd
, "probe", handle_flash_probe_command
, COMMAND_EXEC
,
98 "identify flash bank <num>");
99 register_command(cmd_ctx
, flash_cmd
, "erase_check", handle_flash_erase_check_command
, COMMAND_EXEC
,
100 "check erase state of sectors in flash bank <num>");
101 register_command(cmd_ctx
, flash_cmd
, "protect_check", handle_flash_protect_check_command
, COMMAND_EXEC
,
102 "check protection state of sectors in flash bank <num>");
103 register_command(cmd_ctx
, flash_cmd
, "erase", handle_flash_erase_command
, COMMAND_EXEC
,
104 "erase sectors at <bank> <first> <last>");
105 register_command(cmd_ctx
, flash_cmd
, "write", handle_flash_write_binary_command
, COMMAND_EXEC
,
106 "DEPRECATED, use 'write_binary' or 'write_image' instead");
107 register_command(cmd_ctx
, flash_cmd
, "write_binary", handle_flash_write_binary_command
, COMMAND_EXEC
,
108 "write binary <bank> <file> <offset>");
109 register_command(cmd_ctx
, flash_cmd
, "write_image", handle_flash_write_image_command
, COMMAND_EXEC
,
110 "write image <file> [offset] [type]");
111 register_command(cmd_ctx
, flash_cmd
, "protect", handle_flash_protect_command
, COMMAND_EXEC
,
112 "set protection of sectors at <bank> <first> <last> <on|off>");
118 flash_bank_t
*get_flash_bank_by_num(int num
)
123 for (p
= flash_banks
; p
; p
= p
->next
)
134 /* flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]
136 int handle_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
144 WARNING("incomplete flash_bank configuration");
145 WARNING("flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]");
149 if ((target
= get_target_by_num(strtoul(args
[5], NULL
, 0))) == NULL
)
151 ERROR("target %lu not defined", strtoul(args
[5], NULL
, 0));
155 for (i
= 0; flash_drivers
[i
]; i
++)
157 if (strcmp(args
[0], flash_drivers
[i
]->name
) == 0)
161 /* register flash specific commands */
162 if (flash_drivers
[i
]->register_commands(cmd_ctx
) != ERROR_OK
)
164 ERROR("couldn't register '%s' commands", args
[0]);
168 c
= malloc(sizeof(flash_bank_t
));
170 c
->driver
= flash_drivers
[i
];
171 c
->driver_priv
= NULL
;
172 c
->base
= strtoul(args
[1], NULL
, 0);
173 c
->size
= strtoul(args
[2], NULL
, 0);
174 c
->chip_width
= strtoul(args
[3], NULL
, 0);
175 c
->bus_width
= strtoul(args
[4], NULL
, 0);
178 if (flash_drivers
[i
]->flash_bank_command(cmd_ctx
, cmd
, args
, argc
, c
) != ERROR_OK
)
180 ERROR("'%s' driver rejected flash bank at 0x%8.8x", args
[0], c
->base
);
185 /* put flash bank in linked list */
188 /* find last flash bank */
189 for (p
= flash_banks
; p
&& p
->next
; p
= p
->next
);
202 /* no matching flash driver found */
205 ERROR("flash driver '%s' not found", args
[0]);
212 int handle_flash_banks_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
219 command_print(cmd_ctx
, "no flash banks configured");
223 for (p
= flash_banks
; p
; p
= p
->next
)
225 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
226 i
++, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
232 int handle_flash_info_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
240 command_print(cmd_ctx
, "usage: flash info <num>");
244 for (p
= flash_banks
; p
; p
= p
->next
, i
++)
246 if (i
== strtoul(args
[0], NULL
, 0))
250 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
251 i
, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
252 for (j
= 0; j
< p
->num_sectors
; j
++)
254 char *erase_state
, *protect_state
;
256 if (p
->sectors
[j
].is_erased
== 0)
257 erase_state
= "not erased";
258 else if (p
->sectors
[j
].is_erased
== 1)
259 erase_state
= "erased";
261 erase_state
= "erase state unknown";
263 if (p
->sectors
[j
].is_protected
== 0)
264 protect_state
= "not protected";
265 else if (p
->sectors
[j
].is_protected
== 1)
266 protect_state
= "protected";
268 protect_state
= "protection state unknown";
270 command_print(cmd_ctx
, "\t#%i: 0x%8.8x (0x%xkB) %s, %s",
271 j
, p
->sectors
[j
].offset
, p
->sectors
[j
].size
,
272 erase_state
, protect_state
);
275 p
->driver
->info(p
, buf
, 1024);
276 command_print(cmd_ctx
, "%s", buf
);
283 int handle_flash_probe_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
290 command_print(cmd_ctx
, "usage: flash probe <num>");
294 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
297 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
299 command_print(cmd_ctx
, "flash '%s' found at 0x%8.8x", p
->driver
->name
, p
->base
);
301 else if (retval
== ERROR_FLASH_BANK_INVALID
)
303 command_print(cmd_ctx
, "probing failed for flash bank '#%s' at 0x%8.8x",
308 command_print(cmd_ctx
, "unknown error when probing flash bank '#%s' at 0x%8.8x",
314 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
320 int handle_flash_erase_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
327 command_print(cmd_ctx
, "usage: flash erase_check <num>");
331 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
334 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
336 command_print(cmd_ctx
, "successfully checked erase state", p
->driver
->name
, p
->base
);
340 command_print(cmd_ctx
, "unknown error when checking erase state of flash bank #%s at 0x%8.8x",
346 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
352 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
359 command_print(cmd_ctx
, "usage: flash protect_check <num>");
363 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
366 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
368 command_print(cmd_ctx
, "successfully checked protect state");
370 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
372 command_print(cmd_ctx
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8x", args
[0], p
->base
);
376 command_print(cmd_ctx
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8x", args
[0], p
->base
);
381 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
387 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
391 int first
= strtoul(args
[1], NULL
, 0);
392 int last
= strtoul(args
[2], NULL
, 0);
394 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
398 duration_start_measure(&duration
);
402 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
406 if ((retval
= p
->driver
->erase(p
, first
, last
)) != ERROR_OK
)
410 case ERROR_TARGET_NOT_HALTED
:
411 command_print(cmd_ctx
, "can't work with this flash while target is running");
413 case ERROR_INVALID_ARGUMENTS
:
414 command_print(cmd_ctx
, "usage: flash_erase <bank> <first> <last>");
416 case ERROR_FLASH_BANK_INVALID
:
417 command_print(cmd_ctx
, "no '%s' flash found at 0x%8.8x", p
->driver
->name
, p
->base
);
419 case ERROR_FLASH_OPERATION_FAILED
:
420 command_print(cmd_ctx
, "flash erase error");
422 case ERROR_FLASH_SECTOR_INVALID
:
423 command_print(cmd_ctx
, "sector number(s) invalid");
426 command_print(cmd_ctx
, "erased flash sectors %i to %i", first
, last
);
429 command_print(cmd_ctx
, "unknown error");
434 duration_stop_measure(&duration
, &duration_text
);
436 command_print(cmd_ctx
, "erased sectors %i through %i on flash bank %i in %s", first
, last
, strtoul(args
[0], 0, 0), duration_text
);
442 command_print(cmd_ctx
, "usage: flash erase <bank> <first> <last>");
448 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
452 int first
= strtoul(args
[1], NULL
, 0);
453 int last
= strtoul(args
[2], NULL
, 0);
456 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
459 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
463 if (strcmp(args
[3], "on") == 0)
465 else if (strcmp(args
[3], "off") == 0)
469 command_print(cmd_ctx
, "usage: flash protect <bank> <first> <last> <on|off>");
473 if ((retval
= p
->driver
->protect(p
, set
, first
, last
)) != ERROR_OK
)
477 case ERROR_TARGET_NOT_HALTED
:
478 command_print(cmd_ctx
, "can't work with this flash while target is running");
480 case ERROR_INVALID_ARGUMENTS
:
481 command_print(cmd_ctx
, "usage: flash protect <bank> <first> <last> <on|off>");
483 case ERROR_FLASH_BANK_INVALID
:
484 command_print(cmd_ctx
, "no '%s' flash found at 0x%8.8x", p
->driver
->name
, p
->base
);
486 case ERROR_FLASH_OPERATION_FAILED
:
487 command_print(cmd_ctx
, "flash program error");
489 case ERROR_FLASH_SECTOR_INVALID
:
490 command_print(cmd_ctx
, "sector number(s) invalid");
493 command_print(cmd_ctx
, "protection of flash sectors %i to %i turned %s", first
, last
, args
[3]);
496 command_print(cmd_ctx
, "unknown error");
501 command_print(cmd_ctx
, "%s protection for sectors %i through %i on flash bank %i", (set
) ? "set" : "cleared", first
, last
, strtoul(args
[0], 0, 0));
506 command_print(cmd_ctx
, "usage: flash protect <bank> <first> <last> <on|off>");
512 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
514 target_t
*target
= get_current_target(cmd_ctx
);
528 if (!strcmp(cmd
, "write"))
530 command_print(cmd_ctx
, "'flash write' has been deprecated in favor of 'flash write_binary' and 'flash write_image'");
531 DEBUG("'flash write' has been deprecated in favor of 'flash write_binary' and 'flash write_image'");
536 command_print(cmd_ctx
, "usage: flash write <file> [offset] [type]");
542 ERROR("no target selected");
546 duration_start_measure(&duration
);
550 image
.base_address_set
= 1;
551 image
.base_address
= strtoul(args
[1], NULL
, 0);
555 image
.base_address_set
= 0;
556 image
.base_address
= 0x0;
559 image
.start_address_set
= 0;
561 if (image_open(&image
, args
[0], (argc
== 4) ? args
[2] : NULL
) != ERROR_OK
)
563 command_print(cmd_ctx
, "flash write error: %s", image
.error_str
);
567 failed
= malloc(sizeof(u32
) * image
.num_sections
);
569 if ((retval
= flash_write(target
, &image
, &image_size
, &error_str
, failed
)) != ERROR_OK
)
571 command_print(cmd_ctx
, "failed writing image %s: %s", args
[0], error_str
);
575 for (i
= 0; i
< image
.num_sections
; i
++)
579 command_print(cmd_ctx
, "didn't write section at 0x%8.8x, size 0x%8.8x",
580 image
.sections
[i
].base_address
, image
.sections
[i
].size
);
584 duration_stop_measure(&duration
, &duration_text
);
585 command_print(cmd_ctx
, "wrote %u byte from file %s in %s (%f kb/s)",
586 image_size
, args
[0], duration_text
,
587 (float)image_size
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
595 int handle_flash_write_binary_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
611 command_print(cmd_ctx
, "usage: flash write <bank> <file> <offset>");
615 duration_start_measure(&duration
);
617 offset
= strtoul(args
[2], NULL
, 0);
618 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
621 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
625 if (fileio_open(&fileio
, args
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
627 command_print(cmd_ctx
, "flash write error: %s", fileio
.error_str
);
631 buffer
= malloc(fileio
.size
);
632 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
634 command_print(cmd_ctx
, "flash write error: %s", fileio
.error_str
);
638 if ((retval
= p
->driver
->write(p
, buffer
, offset
, buf_cnt
)) != ERROR_OK
)
640 command_print(cmd_ctx
, "failed writing file %s to flash bank %i at offset 0x%8.8x",
641 args
[1], strtoul(args
[0], NULL
, 0), strtoul(args
[2], NULL
, 0));
644 case ERROR_TARGET_NOT_HALTED
:
645 command_print(cmd_ctx
, "can't work with this flash while target is running");
647 case ERROR_INVALID_ARGUMENTS
:
648 command_print(cmd_ctx
, "usage: flash write <bank> <file> <offset>");
650 case ERROR_FLASH_BANK_INVALID
:
651 command_print(cmd_ctx
, "no '%s' flash found at 0x%8.8x", p
->driver
->name
, p
->base
);
653 case ERROR_FLASH_OPERATION_FAILED
:
654 command_print(cmd_ctx
, "flash program error");
656 case ERROR_FLASH_DST_BREAKS_ALIGNMENT
:
657 command_print(cmd_ctx
, "offset breaks required alignment");
659 case ERROR_FLASH_DST_OUT_OF_BANK
:
660 command_print(cmd_ctx
, "destination is out of flash bank (offset and/or file too large)");
662 case ERROR_FLASH_SECTOR_NOT_ERASED
:
663 command_print(cmd_ctx
, "destination sector(s) not erased");
666 command_print(cmd_ctx
, "unknown error");
672 duration_stop_measure(&duration
, &duration_text
);
673 command_print(cmd_ctx
, "wrote %"PRIi64
" byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)",
674 fileio
.size
, args
[1], strtoul(args
[0], NULL
, 0), offset
, duration_text
,
675 (float)fileio
.size
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
678 fileio_close(&fileio
);
683 /* lookup flash bank by address */
684 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
)
688 /* cycle through bank list */
689 for (c
= flash_banks
; c
; c
= c
->next
)
691 /* check whether address belongs to this flash bank */
692 if ((addr
>= c
->base
) && (addr
< c
->base
+ c
->size
) && target
== c
->target
)
699 /* erase given flash region, selects proper bank according to target and address */
700 int flash_erase(target_t
*target
, u32 addr
, u32 length
)
703 unsigned long sector_size
;
707 if ((c
= get_flash_bank_by_addr(target
, addr
)) == NULL
)
708 return ERROR_FLASH_DST_OUT_OF_BANK
; /* no corresponding bank found */
711 if (c
->size
== 0 || c
->num_sectors
== 0 || c
->size
% c
->num_sectors
)
712 return ERROR_FLASH_BANK_INVALID
;
716 /* special case, erase whole bank when length is zero */
718 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
720 return c
->driver
->erase(c
, 0, c
->num_sectors
- 1);
723 /* check whether it fits */
724 if (addr
+ length
> c
->base
+ c
->size
)
725 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
727 /* calculate sector size */
728 sector_size
= c
->size
/ c
->num_sectors
;
730 /* check alignment */
731 if ((addr
- c
->base
) % sector_size
|| length
% sector_size
)
732 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
734 first
= (addr
- c
->base
) / sector_size
;
735 last
= first
+ length
/ sector_size
- 1;
736 return c
->driver
->erase(c
, first
, last
);
739 int flash_write(target_t
*target
, image_t
*image
, u32
*image_size
, char **error_str
, u32
*failed
)
746 /* for each section in the image */
747 for (section
= 0; section
< image
->num_sections
; section
++)
750 u32 address
= image
->sections
[section
].base_address
;
751 u32 size
= image
->sections
[section
].size
;
758 u32 thisrun_size
= size
;
762 /* find the corresponding flash bank */
763 if ((c
= get_flash_bank_by_addr(target
, address
)) == NULL
)
765 /* mark as failed, and skip the current section */
770 /* check whether it fits, split into multiple runs if not */
771 if ((address
+ size
) > (c
->base
+ c
->size
))
772 thisrun_size
= c
->base
+ c
->size
- address
;
774 buffer
= malloc(thisrun_size
);
775 if (((retval
= image_read_section(image
, section
, offset
, size
, buffer
, &size_read
)) != ERROR_OK
)
776 || (thisrun_size
!= size_read
))
778 *error_str
= malloc(FLASH_MAX_ERROR_STR
);
779 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "error reading from image");
780 return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE
;
783 if ((retval
= c
->driver
->write(c
, buffer
, address
- c
->base
, thisrun_size
)) != ERROR_OK
)
785 /* mark the current section as failed */
787 *error_str
= malloc(FLASH_MAX_ERROR_STR
);
790 case ERROR_TARGET_NOT_HALTED
:
791 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "can't flash image while target is running");
793 case ERROR_INVALID_ARGUMENTS
:
794 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "flash driver can't fulfill request");
796 case ERROR_FLASH_OPERATION_FAILED
:
797 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "flash program error");
799 case ERROR_FLASH_DST_BREAKS_ALIGNMENT
:
800 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "offset breaks required alignment");
802 case ERROR_FLASH_DST_OUT_OF_BANK
:
803 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "no flash mapped at requested address");
805 case ERROR_FLASH_SECTOR_NOT_ERASED
:
806 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "destination sector(s) not erased");
809 snprintf(*error_str
, FLASH_MAX_ERROR_STR
, "unknown error: %i", retval
);
814 /* abort operation */
820 offset
+= thisrun_size
;
821 address
+= thisrun_size
;
822 size
-= thisrun_size
;
825 *image_size
+= image
->sections
[section
].size
;
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)