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_erase_address_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
47 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
48 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
49 int handle_flash_write_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
50 int handle_flash_write_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
51 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
52 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
53 int handle_flash_auto_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
54 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
);
58 extern flash_driver_t lpc2000_flash
;
59 extern flash_driver_t cfi_flash
;
60 extern flash_driver_t at91sam7_flash
;
61 extern flash_driver_t str7x_flash
;
62 extern flash_driver_t str9x_flash
;
63 extern flash_driver_t stellaris_flash
;
64 extern flash_driver_t str9xpec_flash
;
65 extern flash_driver_t stm32x_flash
;
66 extern flash_driver_t tms470_flash
;
67 extern flash_driver_t ecosflash_flash
;
69 flash_driver_t
*flash_drivers
[] =
84 flash_bank_t
*flash_banks
;
85 static command_t
*flash_cmd
;
86 static int auto_erase
= 0;
88 /* wafer thin wrapper for invoking the flash driver */
89 static int flash_driver_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
93 retval
=bank
->driver
->write(bank
, buffer
, offset
, count
);
96 ERROR("error writing to flash at address 0x%08x at offset 0x%8.8x", bank
->base
, offset
);
102 static int flash_driver_erase(struct flash_bank_s
*bank
, int first
, int last
)
106 retval
=bank
->driver
->erase(bank
, first
, last
);
107 if (retval
!=ERROR_OK
)
109 ERROR("failed erasing sectors %d to %d", first
, last
);
115 int flash_driver_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
119 retval
=bank
->driver
->protect(bank
, set
, first
, last
);
120 if (retval
!=ERROR_OK
)
122 ERROR("failed setting protection for areas %d to %d", first
, last
);
129 int flash_register_commands(struct command_context_s
*cmd_ctx
)
131 flash_cmd
= register_command(cmd_ctx
, NULL
, "flash", NULL
, COMMAND_ANY
, NULL
);
133 register_command(cmd_ctx
, flash_cmd
, "bank", handle_flash_bank_command
, COMMAND_CONFIG
, "flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]");
134 register_command(cmd_ctx
, flash_cmd
, "auto_erase", handle_flash_auto_erase_command
, COMMAND_ANY
,
135 "auto erase flash sectors <on|off>");
139 int flash_init_drivers(struct command_context_s
*cmd_ctx
)
143 register_command(cmd_ctx
, flash_cmd
, "banks", handle_flash_banks_command
, COMMAND_EXEC
,
144 "list configured flash banks ");
145 register_command(cmd_ctx
, flash_cmd
, "info", handle_flash_info_command
, COMMAND_EXEC
,
146 "print info about flash bank <num>");
147 register_command(cmd_ctx
, flash_cmd
, "probe", handle_flash_probe_command
, COMMAND_EXEC
,
148 "identify flash bank <num>");
149 register_command(cmd_ctx
, flash_cmd
, "erase_check", handle_flash_erase_check_command
, COMMAND_EXEC
,
150 "check erase state of sectors in flash bank <num>");
151 register_command(cmd_ctx
, flash_cmd
, "protect_check", handle_flash_protect_check_command
, COMMAND_EXEC
,
152 "check protection state of sectors in flash bank <num>");
153 register_command(cmd_ctx
, flash_cmd
, "erase_sector", handle_flash_erase_command
, COMMAND_EXEC
,
154 "erase sectors at <bank> <first> <last>");
155 register_command(cmd_ctx
, flash_cmd
, "erase_address", handle_flash_erase_address_command
, COMMAND_EXEC
,
156 "erase address range <address> <length>");
157 register_command(cmd_ctx
, flash_cmd
, "write_bank", handle_flash_write_bank_command
, COMMAND_EXEC
,
158 "write binary data to <bank> <file> <offset>");
159 register_command(cmd_ctx
, flash_cmd
, "write_image", handle_flash_write_image_command
, COMMAND_EXEC
,
160 "write_image <file> [offset] [type]");
161 register_command(cmd_ctx
, flash_cmd
, "protect", handle_flash_protect_command
, COMMAND_EXEC
,
162 "set protection of sectors at <bank> <first> <last> <on|off>");
168 flash_bank_t
*get_flash_bank_by_num_noprobe(int num
)
173 for (p
= flash_banks
; p
; p
= p
->next
)
180 ERROR("flash bank %d does not exist", num
);
184 flash_bank_t
*get_flash_bank_by_num(int num
)
186 flash_bank_t
*p
= get_flash_bank_by_num_noprobe(num
);
192 retval
= p
->driver
->auto_probe(p
);
194 if (retval
!= ERROR_OK
)
196 ERROR("auto_probe failed %d\n", retval
);
202 int handle_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
210 return ERROR_COMMAND_SYNTAX_ERROR
;
213 if ((target
= get_target_by_num(strtoul(args
[5], NULL
, 0))) == NULL
)
215 ERROR("target %lu not defined", strtoul(args
[5], NULL
, 0));
219 for (i
= 0; flash_drivers
[i
]; i
++)
221 if (strcmp(args
[0], flash_drivers
[i
]->name
) == 0)
225 /* register flash specific commands */
226 if (flash_drivers
[i
]->register_commands(cmd_ctx
) != ERROR_OK
)
228 ERROR("couldn't register '%s' commands", args
[0]);
232 c
= malloc(sizeof(flash_bank_t
));
234 c
->driver
= flash_drivers
[i
];
235 c
->driver_priv
= NULL
;
236 c
->base
= strtoul(args
[1], NULL
, 0);
237 c
->size
= strtoul(args
[2], NULL
, 0);
238 c
->chip_width
= strtoul(args
[3], NULL
, 0);
239 c
->bus_width
= strtoul(args
[4], NULL
, 0);
244 if (flash_drivers
[i
]->flash_bank_command(cmd_ctx
, cmd
, args
, argc
, c
) != ERROR_OK
)
246 ERROR("'%s' driver rejected flash bank at 0x%8.8x", args
[0], c
->base
);
251 /* put flash bank in linked list */
254 /* find last flash bank */
255 for (p
= flash_banks
; p
&& p
->next
; p
= p
->next
);
268 /* no matching flash driver found */
271 ERROR("flash driver '%s' not found", args
[0]);
278 int handle_flash_banks_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
285 command_print(cmd_ctx
, "no flash banks configured");
289 for (p
= flash_banks
; p
; p
= p
->next
)
291 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
292 i
++, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
298 int handle_flash_info_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
306 return ERROR_COMMAND_SYNTAX_ERROR
;
309 for (p
= flash_banks
; p
; p
= p
->next
, i
++)
311 if (i
== strtoul(args
[0], NULL
, 0))
315 /* attempt auto probe */
316 p
->driver
->auto_probe(p
);
318 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
319 i
, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
320 for (j
= 0; j
< p
->num_sectors
; j
++)
322 char *erase_state
, *protect_state
;
324 if (p
->sectors
[j
].is_erased
== 0)
325 erase_state
= "not erased";
326 else if (p
->sectors
[j
].is_erased
== 1)
327 erase_state
= "erased";
329 erase_state
= "erase state unknown";
331 if (p
->sectors
[j
].is_protected
== 0)
332 protect_state
= "not protected";
333 else if (p
->sectors
[j
].is_protected
== 1)
334 protect_state
= "protected";
336 protect_state
= "protection state unknown";
338 command_print(cmd_ctx
, "\t#%i: 0x%8.8x (0x%x %ikB) %s, %s",
339 j
, p
->sectors
[j
].offset
, p
->sectors
[j
].size
, p
->sectors
[j
].size
>>10,
340 erase_state
, protect_state
);
343 p
->driver
->info(p
, buf
, 1024);
344 command_print(cmd_ctx
, "%s", buf
);
351 int handle_flash_probe_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
358 return ERROR_COMMAND_SYNTAX_ERROR
;
361 p
= get_flash_bank_by_num_noprobe(strtoul(args
[0], NULL
, 0));
364 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
366 command_print(cmd_ctx
, "flash '%s' found at 0x%8.8x", p
->driver
->name
, p
->base
);
368 else if (retval
== ERROR_FLASH_BANK_INVALID
)
370 command_print(cmd_ctx
, "probing failed for flash bank '#%s' at 0x%8.8x",
375 command_print(cmd_ctx
, "unknown error when probing flash bank '#%s' at 0x%8.8x",
381 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
387 int handle_flash_erase_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
394 return ERROR_COMMAND_SYNTAX_ERROR
;
397 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
400 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
402 command_print(cmd_ctx
, "successfully checked erase state", p
->driver
->name
, p
->base
);
406 command_print(cmd_ctx
, "unknown error when checking erase state of flash bank #%s at 0x%8.8x",
414 int handle_flash_erase_address_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
423 target_t
*target
= get_current_target(cmd_ctx
);
427 return ERROR_COMMAND_SYNTAX_ERROR
;
430 address
= strtoul(args
[0], NULL
, 0);
431 length
= strtoul(args
[1], NULL
, 0);
434 command_print(cmd_ctx
, "Length must be >0");
435 return ERROR_COMMAND_SYNTAX_ERROR
;
438 p
= get_flash_bank_by_addr(target
, address
);
441 return ERROR_COMMAND_SYNTAX_ERROR
;
444 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
447 duration_start_measure(&duration
);
449 if ((retval
= flash_erase_address_range(target
, address
, length
)) == ERROR_OK
)
451 duration_stop_measure(&duration
, &duration_text
);
452 command_print(cmd_ctx
, "erased address 0x%8.8x length %i in %s", address
, length
, duration_text
);
459 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
466 return ERROR_COMMAND_SYNTAX_ERROR
;
469 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
472 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
474 command_print(cmd_ctx
, "successfully checked protect state");
476 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
478 command_print(cmd_ctx
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8x", args
[0], p
->base
);
482 command_print(cmd_ctx
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8x", args
[0], p
->base
);
487 return ERROR_COMMAND_SYNTAX_ERROR
;
493 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
497 int first
= strtoul(args
[1], NULL
, 0);
498 int last
= strtoul(args
[2], NULL
, 0);
500 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
504 duration_start_measure(&duration
);
508 return ERROR_COMMAND_SYNTAX_ERROR
;
511 if ((retval
= flash_driver_erase(p
, first
, last
)) == ERROR_OK
)
513 duration_stop_measure(&duration
, &duration_text
);
515 command_print(cmd_ctx
, "erased sectors %i through %i on flash bank %i in %s", first
, last
, strtoul(args
[0], 0, 0), duration_text
);
521 return ERROR_COMMAND_SYNTAX_ERROR
;
527 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
531 int first
= strtoul(args
[1], NULL
, 0);
532 int last
= strtoul(args
[2], NULL
, 0);
535 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
538 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
542 if (strcmp(args
[3], "on") == 0)
544 else if (strcmp(args
[3], "off") == 0)
548 return ERROR_COMMAND_SYNTAX_ERROR
;
551 retval
= flash_driver_protect(p
, set
, first
, last
);
552 if (retval
== ERROR_OK
)
554 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));
559 return ERROR_COMMAND_SYNTAX_ERROR
;
566 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
568 target_t
*target
= get_current_target(cmd_ctx
);
580 return ERROR_COMMAND_SYNTAX_ERROR
;
586 ERROR("no target selected");
590 duration_start_measure(&duration
);
594 image
.base_address_set
= 1;
595 image
.base_address
= strtoul(args
[1], NULL
, 0);
599 image
.base_address_set
= 0;
600 image
.base_address
= 0x0;
603 image
.start_address_set
= 0;
605 retval
= image_open(&image
, args
[0], (argc
== 3) ? args
[2] : NULL
);
606 if (retval
!= ERROR_OK
)
611 retval
= flash_write(target
, &image
, &written
, auto_erase
);
613 if (retval
!= ERROR_OK
)
619 duration_stop_measure(&duration
, &duration_text
);
620 if (retval
== ERROR_OK
)
622 command_print(cmd_ctx
, "wrote %u byte from file %s in %s (%f kb/s)",
623 written
, args
[0], duration_text
,
624 (float)written
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
633 int handle_flash_write_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
649 return ERROR_COMMAND_SYNTAX_ERROR
;
652 duration_start_measure(&duration
);
654 offset
= strtoul(args
[2], NULL
, 0);
655 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
658 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
662 if (fileio_open(&fileio
, args
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
667 buffer
= malloc(fileio
.size
);
668 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
673 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
677 duration_stop_measure(&duration
, &duration_text
);
678 if (retval
!=ERROR_OK
)
680 command_print(cmd_ctx
, "wrote %"PRIi64
" byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)",
681 fileio
.size
, args
[1], strtoul(args
[0], NULL
, 0), offset
, duration_text
,
682 (float)fileio
.size
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
686 fileio_close(&fileio
);
691 void flash_set_dirty(void)
696 /* set all flash to require erasing */
697 for (c
= flash_banks
; c
; c
= c
->next
)
699 for (i
= 0; i
< c
->num_sectors
; i
++)
701 c
->sectors
[i
].is_erased
= 0;
706 /* lookup flash bank by address */
707 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
)
711 /* cycle through bank list */
712 for (c
= flash_banks
; c
; c
= c
->next
)
715 retval
= c
->driver
->auto_probe(c
);
717 if (retval
!= ERROR_OK
)
719 ERROR("auto_probe failed %d\n", retval
);
722 /* check whether address belongs to this flash bank */
723 if ((addr
>= c
->base
) && (addr
< c
->base
+ c
->size
) && target
== c
->target
)
726 ERROR("No flash at address 0x%08x\n", addr
);
730 /* erase given flash region, selects proper bank according to target and address */
731 int flash_erase_address_range(target_t
*target
, u32 addr
, u32 length
)
738 if ((c
= get_flash_bank_by_addr(target
, addr
)) == NULL
)
739 return ERROR_FLASH_DST_OUT_OF_BANK
; /* no corresponding bank found */
741 if (c
->size
== 0 || c
->num_sectors
== 0)
742 return ERROR_FLASH_BANK_INVALID
;
746 /* special case, erase whole bank when length is zero */
748 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
750 return flash_driver_erase(c
, 0, c
->num_sectors
- 1);
753 /* check whether it fits */
754 if (addr
+ length
> c
->base
+ c
->size
)
755 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
759 for (i
= 0; i
< c
->num_sectors
; i
++)
761 /* check whether sector overlaps with the given range and is not yet erased */
762 if (addr
< c
->sectors
[i
].offset
+ c
->sectors
[i
].size
&& addr
+ length
> c
->sectors
[i
].offset
&& c
->sectors
[i
].is_erased
!= 1) {
763 /* if first is not set yet then this is the first sector */
766 last
= i
; /* and it is the last one so far in any case */
770 if( first
== -1 || last
== -1 )
773 return flash_driver_erase(c
, first
, last
);
776 /* write (optional verify) an image to flash memory of the given target */
777 int flash_write(target_t
*target
, image_t
*image
, u32
*written
, int erase
)
793 /* assume all sectors need erasing - stops any problems
794 * when flash_write is called multiple times */
799 /* loop until we reach end of the image */
800 while (section
< image
->num_sections
)
806 u32 run_address
= image
->sections
[section
].base_address
+ section_offset
;
807 u32 run_size
= image
->sections
[section
].size
- section_offset
;
809 if (image
->sections
[section
].size
== 0)
811 WARNING("empty section %d", section
);
817 /* find the corresponding flash bank */
818 if ((c
= get_flash_bank_by_addr(target
, run_address
)) == NULL
)
820 section
++; /* and skip it */
825 /* collect consecutive sections which fall into the same bank */
826 section_first
= section
;
827 section_last
= section
;
828 while ((run_address
+ run_size
< c
->base
+ c
->size
)
829 && (section_last
+ 1 < image
->num_sections
))
831 if (image
->sections
[section_last
+ 1].base_address
< (run_address
+ run_size
))
833 DEBUG("section %d out of order(very slightly surprising, but supported)", section_last
+ 1);
836 if (image
->sections
[section_last
+ 1].base_address
!= (run_address
+ run_size
))
838 run_size
+= image
->sections
[++section_last
].size
;
841 /* fit the run into bank constraints */
842 if (run_address
+ run_size
> c
->base
+ c
->size
)
843 run_size
= c
->base
+ c
->size
- run_address
;
845 /* allocate buffer */
846 buffer
= malloc(run_size
);
849 /* read sections to the buffer */
850 while (buffer_size
< run_size
)
854 if (buffer_size
- run_size
<= image
->sections
[section
].size
- section_offset
)
855 size_read
= buffer_size
- run_size
;
857 size_read
= image
->sections
[section
].size
- section_offset
;
859 if ((retval
= image_read_section(image
, section
, section_offset
,
860 size_read
, buffer
+ buffer_size
, &size_read
)) != ERROR_OK
|| size_read
== 0)
867 buffer_size
+= size_read
;
868 section_offset
+= size_read
;
870 if (section_offset
>= image
->sections
[section
].size
)
881 /* calculate and erase sectors */
882 retval
= flash_erase_address_range( target
, run_address
, run_size
);
885 if (retval
== ERROR_OK
)
887 /* write flash sectors */
888 retval
= flash_driver_write(c
, buffer
, run_address
- c
->base
, run_size
);
893 if (retval
!= ERROR_OK
)
895 return retval
; /* abort operation */
899 *written
+= run_size
; /* add run size to total written counter */
905 int handle_flash_auto_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
909 return ERROR_COMMAND_SYNTAX_ERROR
;
913 if (strcmp(args
[0], "on") == 0)
915 else if (strcmp(args
[0], "off") == 0)
918 return ERROR_COMMAND_SYNTAX_ERROR
;
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)