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 banks %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 protecting banks %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
)
608 command_print(cmd_ctx
, "image_open error: %s", image
.error_str
);
612 retval
= flash_write(target
, &image
, &written
, auto_erase
);
614 if (retval
!= ERROR_OK
)
620 duration_stop_measure(&duration
, &duration_text
);
621 if (retval
== ERROR_OK
)
623 command_print(cmd_ctx
, "wrote %u byte from file %s in %s (%f kb/s)",
624 written
, args
[0], duration_text
,
625 (float)written
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
634 int handle_flash_write_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
650 return ERROR_COMMAND_SYNTAX_ERROR
;
653 duration_start_measure(&duration
);
655 offset
= strtoul(args
[2], NULL
, 0);
656 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
659 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
663 if (fileio_open(&fileio
, args
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
665 command_print(cmd_ctx
, "flash write_binary error: %s", fileio
.error_str
);
669 buffer
= malloc(fileio
.size
);
670 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
672 command_print(cmd_ctx
, "flash write_binary error: %s", fileio
.error_str
);
676 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
680 duration_stop_measure(&duration
, &duration_text
);
681 if (retval
!=ERROR_OK
)
683 command_print(cmd_ctx
, "wrote %"PRIi64
" byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)",
684 fileio
.size
, args
[1], strtoul(args
[0], NULL
, 0), offset
, duration_text
,
685 (float)fileio
.size
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
689 fileio_close(&fileio
);
694 void flash_set_dirty(void)
699 /* set all flash to require erasing */
700 for (c
= flash_banks
; c
; c
= c
->next
)
702 for (i
= 0; i
< c
->num_sectors
; i
++)
704 c
->sectors
[i
].is_erased
= 0;
709 /* lookup flash bank by address */
710 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
)
714 /* cycle through bank list */
715 for (c
= flash_banks
; c
; c
= c
->next
)
718 retval
= c
->driver
->auto_probe(c
);
720 if (retval
!= ERROR_OK
)
722 ERROR("auto_probe failed %d\n", retval
);
725 /* check whether address belongs to this flash bank */
726 if ((addr
>= c
->base
) && (addr
< c
->base
+ c
->size
) && target
== c
->target
)
729 ERROR("No flash at address 0x%08x\n", addr
);
733 /* erase given flash region, selects proper bank according to target and address */
734 int flash_erase_address_range(target_t
*target
, u32 addr
, u32 length
)
741 if ((c
= get_flash_bank_by_addr(target
, addr
)) == NULL
)
742 return ERROR_FLASH_DST_OUT_OF_BANK
; /* no corresponding bank found */
744 if (c
->size
== 0 || c
->num_sectors
== 0)
745 return ERROR_FLASH_BANK_INVALID
;
749 /* special case, erase whole bank when length is zero */
751 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
753 return flash_driver_erase(c
, 0, c
->num_sectors
- 1);
756 /* check whether it fits */
757 if (addr
+ length
> c
->base
+ c
->size
)
758 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
762 for (i
= 0; i
< c
->num_sectors
; i
++)
764 /* check whether sector overlaps with the given range and is not yet erased */
765 if (addr
< c
->sectors
[i
].offset
+ c
->sectors
[i
].size
&& addr
+ length
> c
->sectors
[i
].offset
&& c
->sectors
[i
].is_erased
!= 1) {
766 /* if first is not set yet then this is the first sector */
769 last
= i
; /* and it is the last one so far in any case */
773 if( first
== -1 || last
== -1 )
776 return flash_driver_erase(c
, first
, last
);
779 /* write (optional verify) an image to flash memory of the given target */
780 int flash_write(target_t
*target
, image_t
*image
, u32
*written
, int erase
)
796 /* assume all sectors need erasing - stops any problems
797 * when flash_write is called multiple times */
802 /* loop until we reach end of the image */
803 while (section
< image
->num_sections
)
809 u32 run_address
= image
->sections
[section
].base_address
+ section_offset
;
810 u32 run_size
= image
->sections
[section
].size
- section_offset
;
812 if (image
->sections
[section
].size
== 0)
814 WARNING("empty section %d", section
);
820 /* find the corresponding flash bank */
821 if ((c
= get_flash_bank_by_addr(target
, run_address
)) == NULL
)
823 section
++; /* and skip it */
828 /* collect consecutive sections which fall into the same bank */
829 section_first
= section
;
830 section_last
= section
;
831 while ((run_address
+ run_size
< c
->base
+ c
->size
)
832 && (section_last
+ 1 < image
->num_sections
))
834 if (image
->sections
[section_last
+ 1].base_address
< (run_address
+ run_size
))
836 DEBUG("section %d out of order(very slightly surprising, but supported)", section_last
+ 1);
839 if (image
->sections
[section_last
+ 1].base_address
!= (run_address
+ run_size
))
841 run_size
+= image
->sections
[++section_last
].size
;
844 /* fit the run into bank constraints */
845 if (run_address
+ run_size
> c
->base
+ c
->size
)
846 run_size
= c
->base
+ c
->size
- run_address
;
848 /* allocate buffer */
849 buffer
= malloc(run_size
);
852 /* read sections to the buffer */
853 while (buffer_size
< run_size
)
857 if (buffer_size
- run_size
<= image
->sections
[section
].size
- section_offset
)
858 size_read
= buffer_size
- run_size
;
860 size_read
= image
->sections
[section
].size
- section_offset
;
862 if ((retval
= image_read_section(image
, section
, section_offset
,
863 size_read
, buffer
+ buffer_size
, &size_read
)) != ERROR_OK
|| size_read
== 0)
870 buffer_size
+= size_read
;
871 section_offset
+= size_read
;
873 if (section_offset
>= image
->sections
[section
].size
)
884 /* calculate and erase sectors */
885 retval
= flash_erase_address_range( target
, run_address
, run_size
);
888 if (retval
== ERROR_OK
)
890 /* write flash sectors */
891 retval
= flash_driver_write(c
, buffer
, run_address
- c
->base
, run_size
);
896 if (retval
!= ERROR_OK
)
898 return retval
; /* abort operation */
902 *written
+= run_size
; /* add run size to total written counter */
908 int handle_flash_auto_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
912 return ERROR_COMMAND_SYNTAX_ERROR
;
916 if (strcmp(args
[0], "on") == 0)
918 else if (strcmp(args
[0], "off") == 0)
921 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)