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 (%d)", bank
->base
, offset
, retval
);
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 (%d)", first
, last
, retval
);
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 (%d)", first
, last
, retval
);
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 int flash_get_bank_count()
188 for (p
= flash_banks
; p
; p
= p
->next
)
195 flash_bank_t
*get_flash_bank_by_num(int num
)
197 flash_bank_t
*p
= get_flash_bank_by_num_noprobe(num
);
203 retval
= p
->driver
->auto_probe(p
);
205 if (retval
!= ERROR_OK
)
207 ERROR("auto_probe failed %d\n", retval
);
213 int handle_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
221 return ERROR_COMMAND_SYNTAX_ERROR
;
224 if ((target
= get_target_by_num(strtoul(args
[5], NULL
, 0))) == NULL
)
226 ERROR("target %lu not defined", strtoul(args
[5], NULL
, 0));
230 for (i
= 0; flash_drivers
[i
]; i
++)
232 if (strcmp(args
[0], flash_drivers
[i
]->name
) == 0)
236 /* register flash specific commands */
237 if (flash_drivers
[i
]->register_commands(cmd_ctx
) != ERROR_OK
)
239 ERROR("couldn't register '%s' commands", args
[0]);
243 c
= malloc(sizeof(flash_bank_t
));
245 c
->driver
= flash_drivers
[i
];
246 c
->driver_priv
= NULL
;
247 c
->base
= strtoul(args
[1], NULL
, 0);
248 c
->size
= strtoul(args
[2], NULL
, 0);
249 c
->chip_width
= strtoul(args
[3], NULL
, 0);
250 c
->bus_width
= strtoul(args
[4], NULL
, 0);
255 if (flash_drivers
[i
]->flash_bank_command(cmd_ctx
, cmd
, args
, argc
, c
) != ERROR_OK
)
257 ERROR("'%s' driver rejected flash bank at 0x%8.8x", args
[0], c
->base
);
262 /* put flash bank in linked list */
265 /* find last flash bank */
266 for (p
= flash_banks
; p
&& p
->next
; p
= p
->next
);
279 /* no matching flash driver found */
282 ERROR("flash driver '%s' not found", args
[0]);
289 int handle_flash_banks_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
296 command_print(cmd_ctx
, "no flash banks configured");
300 for (p
= flash_banks
; p
; p
= p
->next
)
302 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
303 i
++, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
309 int handle_flash_info_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
318 return ERROR_COMMAND_SYNTAX_ERROR
;
321 for (p
= flash_banks
; p
; p
= p
->next
, i
++)
323 if (i
== strtoul(args
[0], NULL
, 0))
327 /* attempt auto probe */
328 p
->driver
->auto_probe(p
);
330 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
331 i
, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
332 for (j
= 0; j
< p
->num_sectors
; j
++)
334 char *erase_state
, *protect_state
;
336 if (p
->sectors
[j
].is_erased
== 0)
337 erase_state
= "not erased";
338 else if (p
->sectors
[j
].is_erased
== 1)
339 erase_state
= "erased";
341 erase_state
= "erase state unknown";
343 if (p
->sectors
[j
].is_protected
== 0)
344 protect_state
= "not protected";
345 else if (p
->sectors
[j
].is_protected
== 1)
346 protect_state
= "protected";
348 protect_state
= "protection state unknown";
350 command_print(cmd_ctx
, "\t#%i: 0x%8.8x (0x%x %ikB) %s, %s",
351 j
, p
->sectors
[j
].offset
, p
->sectors
[j
].size
, p
->sectors
[j
].size
>>10,
352 erase_state
, protect_state
);
355 *buf
= '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
356 retval
= p
->driver
->info(p
, buf
, sizeof(buf
));
357 command_print(cmd_ctx
, "%s", buf
);
358 if (retval
!= ERROR_OK
)
359 ERROR("error retrieving flash info (%d)", retval
);
366 int handle_flash_probe_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
373 return ERROR_COMMAND_SYNTAX_ERROR
;
376 p
= get_flash_bank_by_num_noprobe(strtoul(args
[0], NULL
, 0));
379 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
381 command_print(cmd_ctx
, "flash '%s' found at 0x%8.8x", p
->driver
->name
, p
->base
);
383 else if (retval
== ERROR_FLASH_BANK_INVALID
)
385 command_print(cmd_ctx
, "probing failed for flash bank '#%s' at 0x%8.8x",
390 command_print(cmd_ctx
, "unknown error when probing flash bank '#%s' at 0x%8.8x",
396 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
402 int handle_flash_erase_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
409 return ERROR_COMMAND_SYNTAX_ERROR
;
412 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
415 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
417 command_print(cmd_ctx
, "successfully checked erase state", p
->driver
->name
, p
->base
);
421 command_print(cmd_ctx
, "unknown error when checking erase state of flash bank #%s at 0x%8.8x",
429 int handle_flash_erase_address_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
438 target_t
*target
= get_current_target(cmd_ctx
);
442 return ERROR_COMMAND_SYNTAX_ERROR
;
445 address
= strtoul(args
[0], NULL
, 0);
446 length
= strtoul(args
[1], NULL
, 0);
449 command_print(cmd_ctx
, "Length must be >0");
450 return ERROR_COMMAND_SYNTAX_ERROR
;
453 p
= get_flash_bank_by_addr(target
, address
);
456 return ERROR_COMMAND_SYNTAX_ERROR
;
459 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
462 duration_start_measure(&duration
);
464 if ((retval
= flash_erase_address_range(target
, address
, length
)) == ERROR_OK
)
466 duration_stop_measure(&duration
, &duration_text
);
467 command_print(cmd_ctx
, "erased address 0x%8.8x length %i in %s", address
, length
, duration_text
);
474 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
481 return ERROR_COMMAND_SYNTAX_ERROR
;
484 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
487 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
489 command_print(cmd_ctx
, "successfully checked protect state");
491 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
493 command_print(cmd_ctx
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8x", args
[0], p
->base
);
497 command_print(cmd_ctx
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8x", args
[0], p
->base
);
502 return ERROR_COMMAND_SYNTAX_ERROR
;
508 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
512 int first
= strtoul(args
[1], NULL
, 0);
513 int last
= strtoul(args
[2], NULL
, 0);
515 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
519 duration_start_measure(&duration
);
523 return ERROR_COMMAND_SYNTAX_ERROR
;
526 if ((retval
= flash_driver_erase(p
, first
, last
)) == ERROR_OK
)
528 duration_stop_measure(&duration
, &duration_text
);
530 command_print(cmd_ctx
, "erased sectors %i through %i on flash bank %i in %s", first
, last
, strtoul(args
[0], 0, 0), duration_text
);
536 return ERROR_COMMAND_SYNTAX_ERROR
;
542 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
546 int first
= strtoul(args
[1], NULL
, 0);
547 int last
= strtoul(args
[2], NULL
, 0);
550 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
553 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
557 if (strcmp(args
[3], "on") == 0)
559 else if (strcmp(args
[3], "off") == 0)
563 return ERROR_COMMAND_SYNTAX_ERROR
;
566 retval
= flash_driver_protect(p
, set
, first
, last
);
567 if (retval
== ERROR_OK
)
569 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));
574 return ERROR_COMMAND_SYNTAX_ERROR
;
581 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
583 target_t
*target
= get_current_target(cmd_ctx
);
595 return ERROR_COMMAND_SYNTAX_ERROR
;
601 ERROR("no target selected");
605 duration_start_measure(&duration
);
609 image
.base_address_set
= 1;
610 image
.base_address
= strtoul(args
[1], NULL
, 0);
614 image
.base_address_set
= 0;
615 image
.base_address
= 0x0;
618 image
.start_address_set
= 0;
620 retval
= image_open(&image
, args
[0], (argc
== 3) ? args
[2] : NULL
);
621 if (retval
!= ERROR_OK
)
626 retval
= flash_write(target
, &image
, &written
, auto_erase
);
628 if (retval
!= ERROR_OK
)
634 duration_stop_measure(&duration
, &duration_text
);
635 if (retval
== ERROR_OK
)
637 command_print(cmd_ctx
, "wrote %u byte from file %s in %s (%f kb/s)",
638 written
, args
[0], duration_text
,
639 (float)written
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
648 int handle_flash_write_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
664 return ERROR_COMMAND_SYNTAX_ERROR
;
667 duration_start_measure(&duration
);
669 offset
= strtoul(args
[2], NULL
, 0);
670 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
673 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
677 if (fileio_open(&fileio
, args
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
682 buffer
= malloc(fileio
.size
);
683 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
688 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
692 duration_stop_measure(&duration
, &duration_text
);
693 if (retval
!=ERROR_OK
)
695 command_print(cmd_ctx
, "wrote %"PRIi64
" byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)",
696 fileio
.size
, args
[1], strtoul(args
[0], NULL
, 0), offset
, duration_text
,
697 (float)fileio
.size
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
701 fileio_close(&fileio
);
706 void flash_set_dirty(void)
711 /* set all flash to require erasing */
712 for (c
= flash_banks
; c
; c
= c
->next
)
714 for (i
= 0; i
< c
->num_sectors
; i
++)
716 c
->sectors
[i
].is_erased
= 0;
721 /* lookup flash bank by address */
722 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
)
726 /* cycle through bank list */
727 for (c
= flash_banks
; c
; c
= c
->next
)
730 retval
= c
->driver
->auto_probe(c
);
732 if (retval
!= ERROR_OK
)
734 ERROR("auto_probe failed %d\n", retval
);
737 /* check whether address belongs to this flash bank */
738 if ((addr
>= c
->base
) && (addr
< c
->base
+ c
->size
) && target
== c
->target
)
741 ERROR("No flash at address 0x%08x\n", addr
);
745 /* erase given flash region, selects proper bank according to target and address */
746 int flash_erase_address_range(target_t
*target
, u32 addr
, u32 length
)
753 if ((c
= get_flash_bank_by_addr(target
, addr
)) == NULL
)
754 return ERROR_FLASH_DST_OUT_OF_BANK
; /* no corresponding bank found */
756 if (c
->size
== 0 || c
->num_sectors
== 0)
757 return ERROR_FLASH_BANK_INVALID
;
761 /* special case, erase whole bank when length is zero */
763 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
765 return flash_driver_erase(c
, 0, c
->num_sectors
- 1);
768 /* check whether it fits */
769 if (addr
+ length
> c
->base
+ c
->size
)
770 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
774 for (i
= 0; i
< c
->num_sectors
; i
++)
776 /* check whether sector overlaps with the given range and is not yet erased */
777 if (addr
< c
->sectors
[i
].offset
+ c
->sectors
[i
].size
&& addr
+ length
> c
->sectors
[i
].offset
&& c
->sectors
[i
].is_erased
!= 1) {
778 /* if first is not set yet then this is the first sector */
781 last
= i
; /* and it is the last one so far in any case */
785 if( first
== -1 || last
== -1 )
788 return flash_driver_erase(c
, first
, last
);
791 /* write (optional verify) an image to flash memory of the given target */
792 int flash_write(target_t
*target
, image_t
*image
, u32
*written
, int erase
)
808 /* assume all sectors need erasing - stops any problems
809 * when flash_write is called multiple times */
814 /* loop until we reach end of the image */
815 while (section
< image
->num_sections
)
821 u32 run_address
= image
->sections
[section
].base_address
+ section_offset
;
822 u32 run_size
= image
->sections
[section
].size
- section_offset
;
824 if (image
->sections
[section
].size
== 0)
826 WARNING("empty section %d", section
);
832 /* find the corresponding flash bank */
833 if ((c
= get_flash_bank_by_addr(target
, run_address
)) == NULL
)
835 section
++; /* and skip it */
840 /* collect consecutive sections which fall into the same bank */
841 section_first
= section
;
842 section_last
= section
;
843 while ((run_address
+ run_size
< c
->base
+ c
->size
)
844 && (section_last
+ 1 < image
->num_sections
))
846 if (image
->sections
[section_last
+ 1].base_address
< (run_address
+ run_size
))
848 DEBUG("section %d out of order(very slightly surprising, but supported)", section_last
+ 1);
851 if (image
->sections
[section_last
+ 1].base_address
!= (run_address
+ run_size
))
853 run_size
+= image
->sections
[++section_last
].size
;
856 /* fit the run into bank constraints */
857 if (run_address
+ run_size
> c
->base
+ c
->size
)
858 run_size
= c
->base
+ c
->size
- run_address
;
860 /* allocate buffer */
861 buffer
= malloc(run_size
);
864 /* read sections to the buffer */
865 while (buffer_size
< run_size
)
869 if (buffer_size
- run_size
<= image
->sections
[section
].size
- section_offset
)
870 size_read
= buffer_size
- run_size
;
872 size_read
= image
->sections
[section
].size
- section_offset
;
874 if ((retval
= image_read_section(image
, section
, section_offset
,
875 size_read
, buffer
+ buffer_size
, &size_read
)) != ERROR_OK
|| size_read
== 0)
882 buffer_size
+= size_read
;
883 section_offset
+= size_read
;
885 if (section_offset
>= image
->sections
[section
].size
)
896 /* calculate and erase sectors */
897 retval
= flash_erase_address_range( target
, run_address
, run_size
);
900 if (retval
== ERROR_OK
)
902 /* write flash sectors */
903 retval
= flash_driver_write(c
, buffer
, run_address
- c
->base
, run_size
);
908 if (retval
!= ERROR_OK
)
910 return retval
; /* abort operation */
914 *written
+= run_size
; /* add run size to total written counter */
920 int handle_flash_auto_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
924 return ERROR_COMMAND_SYNTAX_ERROR
;
927 if (strcmp(args
[0], "on") == 0)
929 else if (strcmp(args
[0], "off") == 0)
932 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)