1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
4 * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
5 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
26 #include <helper/time_support.h>
27 #include <target/image.h>
29 COMMAND_HELPER(flash_command_get_bank
, unsigned name_index
,
30 struct flash_bank
**bank
)
32 const char *name
= CMD_ARGV
[name_index
];
33 *bank
= get_flash_bank_by_name(name
);
38 COMMAND_PARSE_NUMBER(uint
, name
, bank_num
);
40 *bank
= get_flash_bank_by_num(bank_num
);
43 command_print(CMD_CTX
, "flash bank '%s' not found", name
);
44 return ERROR_INVALID_ARGUMENTS
;
50 COMMAND_HANDLER(handle_flash_info_command
)
58 return ERROR_COMMAND_SYNTAX_ERROR
;
61 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], bank_nr
);
63 for (p
= flash_bank_list(); p
; p
= p
->next
, i
++)
70 /* attempt auto probe */
71 if ((retval
= p
->driver
->auto_probe(p
)) != ERROR_OK
)
74 command_print(CMD_CTX
,
75 "#%" PRIi32
" : %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", buswidth %i, chipwidth %i",
82 for (j
= 0; j
< p
->num_sectors
; j
++)
86 if (p
->sectors
[j
].is_protected
== 0)
87 protect_state
= "not protected";
88 else if (p
->sectors
[j
].is_protected
== 1)
89 protect_state
= "protected";
91 protect_state
= "protection state unknown";
93 command_print(CMD_CTX
,
94 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
98 p
->sectors
[j
].size
>> 10,
102 *buf
= '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
103 retval
= p
->driver
->info(p
, buf
, sizeof(buf
));
104 command_print(CMD_CTX
, "%s", buf
);
105 if (retval
!= ERROR_OK
)
106 LOG_ERROR("error retrieving flash info (%d)", retval
);
112 COMMAND_HANDLER(handle_flash_probe_command
)
118 return ERROR_COMMAND_SYNTAX_ERROR
;
122 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], bank_nr
);
123 struct flash_bank
*p
= get_flash_bank_by_num_noprobe(bank_nr
);
126 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
128 command_print(CMD_CTX
, "flash '%s' found at 0x%8.8" PRIx32
, p
->driver
->name
, p
->base
);
130 else if (retval
== ERROR_FLASH_BANK_INVALID
)
132 command_print(CMD_CTX
, "probing failed for flash bank '#%s' at 0x%8.8" PRIx32
,
133 CMD_ARGV
[0], p
->base
);
137 command_print(CMD_CTX
, "unknown error when probing flash bank '#%s' at 0x%8.8" PRIx32
,
138 CMD_ARGV
[0], p
->base
);
143 command_print(CMD_CTX
, "flash bank '#%s' is out of bounds", CMD_ARGV
[0]);
149 COMMAND_HANDLER(handle_flash_erase_check_command
)
153 return ERROR_COMMAND_SYNTAX_ERROR
;
156 struct flash_bank
*p
;
157 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
158 if (ERROR_OK
!= retval
)
162 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
164 command_print(CMD_CTX
, "successfully checked erase state");
168 command_print(CMD_CTX
, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32
,
169 CMD_ARGV
[0], p
->base
);
172 for (j
= 0; j
< p
->num_sectors
; j
++)
176 if (p
->sectors
[j
].is_erased
== 0)
177 erase_state
= "not erased";
178 else if (p
->sectors
[j
].is_erased
== 1)
179 erase_state
= "erased";
181 erase_state
= "erase state unknown";
183 command_print(CMD_CTX
,
184 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
186 p
->sectors
[j
].offset
,
188 p
->sectors
[j
].size
>> 10,
195 COMMAND_HANDLER(handle_flash_erase_address_command
)
197 struct flash_bank
*p
;
202 struct target
*target
= get_current_target(CMD_CTX
);
205 return ERROR_COMMAND_SYNTAX_ERROR
;
207 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], address
);
208 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], length
);
211 command_print(CMD_CTX
, "Length must be >0");
212 return ERROR_COMMAND_SYNTAX_ERROR
;
215 p
= get_flash_bank_by_addr(target
, address
);
221 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
224 struct duration bench
;
225 duration_start(&bench
);
227 retval
= flash_erase_address_range(target
, address
, length
);
229 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
231 command_print(CMD_CTX
, "erased address 0x%8.8x (length %i)"
232 " in %fs (%0.3f kb/s)", address
, length
,
233 duration_elapsed(&bench
), duration_kbps(&bench
, length
));
239 COMMAND_HANDLER(handle_flash_protect_check_command
)
242 return ERROR_COMMAND_SYNTAX_ERROR
;
244 struct flash_bank
*p
;
245 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
246 if (ERROR_OK
!= retval
)
249 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
251 command_print(CMD_CTX
, "successfully checked protect state");
253 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
255 command_print(CMD_CTX
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
259 command_print(CMD_CTX
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
265 static int flash_check_sector_parameters(struct command_context
*cmd_ctx
,
266 uint32_t first
, uint32_t last
, uint32_t num_sectors
)
268 if (!(first
<= last
)) {
269 command_print(cmd_ctx
, "ERROR: "
270 "first sector must be <= last sector");
274 if (!(last
<= (num_sectors
- 1))) {
275 command_print(cmd_ctx
, "ERROR: last sector must be <= %d",
276 (int) num_sectors
- 1);
283 COMMAND_HANDLER(handle_flash_erase_command
)
286 return ERROR_COMMAND_SYNTAX_ERROR
;
292 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
293 struct flash_bank
*p
= get_flash_bank_by_num(bank_nr
);
297 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
298 if (strcmp(CMD_ARGV
[2], "last") == 0)
299 last
= p
->num_sectors
- 1;
301 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
304 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
305 first
, last
, p
->num_sectors
)) != ERROR_OK
)
308 struct duration bench
;
309 duration_start(&bench
);
311 retval
= flash_driver_erase(p
, first
, last
);
313 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
315 command_print(CMD_CTX
, "erased sectors %" PRIu32
" "
316 "through %" PRIu32
" on flash bank %" PRIu32
" "
317 "in %fs", first
, last
, bank_nr
, duration_elapsed(&bench
));
323 COMMAND_HANDLER(handle_flash_protect_command
)
326 return ERROR_COMMAND_SYNTAX_ERROR
;
332 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
333 struct flash_bank
*p
= get_flash_bank_by_num(bank_nr
);
337 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
338 if (strcmp(CMD_ARGV
[2], "last") == 0)
339 last
= p
->num_sectors
- 1;
341 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
344 COMMAND_PARSE_ON_OFF(CMD_ARGV
[3], set
);
347 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
348 first
, last
, p
->num_sectors
)) != ERROR_OK
)
351 retval
= flash_driver_protect(p
, set
, first
, last
);
352 if (retval
== ERROR_OK
) {
353 command_print(CMD_CTX
, "%s protection for sectors %i "
354 "through %i on flash bank %i",
355 (set
) ? "set" : "cleared", (int) first
,
356 (int) last
, (int) bank_nr
);
362 COMMAND_HANDLER(handle_flash_write_image_command
)
364 struct target
*target
= get_current_target(CMD_CTX
);
373 return ERROR_COMMAND_SYNTAX_ERROR
;
376 /* flash auto-erase is disabled by default*/
378 bool auto_unlock
= false;
382 if (strcmp(CMD_ARGV
[0], "erase") == 0)
387 command_print(CMD_CTX
, "auto erase enabled");
388 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0)
393 command_print(CMD_CTX
, "auto unlock enabled");
402 return ERROR_COMMAND_SYNTAX_ERROR
;
407 LOG_ERROR("no target selected");
411 struct duration bench
;
412 duration_start(&bench
);
416 image
.base_address_set
= 1;
417 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], image
.base_address
);
421 image
.base_address_set
= 0;
422 image
.base_address
= 0x0;
425 image
.start_address_set
= 0;
427 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
428 if (retval
!= ERROR_OK
)
433 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
434 if (retval
!= ERROR_OK
)
440 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
442 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes from file %s "
443 "in %fs (%0.3f kb/s)", written
, CMD_ARGV
[0],
444 duration_elapsed(&bench
), duration_kbps(&bench
, written
));
452 COMMAND_HANDLER(handle_flash_fill_command
)
459 uint32_t cur_size
= 0;
460 uint32_t chunk_count
;
461 struct target
*target
= get_current_target(CMD_CTX
);
464 int retval
= ERROR_OK
;
466 static size_t const chunksize
= 1024;
467 uint8_t *chunk
= malloc(chunksize
);
471 uint8_t *readback
= malloc(chunksize
);
472 if (readback
== NULL
)
481 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
486 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
487 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], pattern
);
488 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], count
);
505 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
509 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
513 for (i
= 0; i
< chunk_count
; i
++)
515 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
519 for (i
= 0; i
< chunk_count
; i
++)
521 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
525 memset(chunk
, pattern
, chunk_count
);
528 LOG_ERROR("BUG: can't happen");
532 struct duration bench
;
533 duration_start(&bench
);
535 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
)
537 struct flash_bank
*bank
;
539 bank
= get_flash_bank_by_addr(target
, address
);
546 cur_size
= MIN((count
* wordsize
- wrote
), chunksize
);
547 err
= flash_driver_write(bank
, chunk
, address
- bank
->base
+ wrote
, cur_size
);
554 err
= target_read_buffer(target
, address
+ wrote
, cur_size
, readback
);
562 for (i
= 0; i
< cur_size
; i
++)
564 if (readback
[i
]!=chunk
[i
])
566 LOG_ERROR("Verfication error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
567 address
+ wrote
+ i
, readback
[i
], chunk
[i
]);
574 if (duration_measure(&bench
) == ERROR_OK
)
576 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes to 0x%8.8" PRIx32
577 " in %fs (%0.3f kb/s)", wrote
, address
,
578 duration_elapsed(&bench
), duration_kbps(&bench
, wrote
));
588 COMMAND_HANDLER(handle_flash_write_bank_command
)
592 struct fileio fileio
;
595 return ERROR_COMMAND_SYNTAX_ERROR
;
597 struct duration bench
;
598 duration_start(&bench
);
600 struct flash_bank
*p
;
601 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
602 if (ERROR_OK
!= retval
)
605 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
607 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
612 buffer
= malloc(fileio
.size
);
614 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
617 fileio_close(&fileio
);
621 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
626 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
628 command_print(CMD_CTX
, "wrote %zu bytes from file %s to flash bank %u"
629 " at offset 0x%8.8" PRIx32
" in %fs (%0.3f kb/s)",
630 fileio
.size
, CMD_ARGV
[1], p
->bank_number
, offset
,
631 duration_elapsed(&bench
), duration_kbps(&bench
, fileio
.size
));
634 fileio_close(&fileio
);
639 void flash_set_dirty(void)
641 struct flash_bank
*c
;
644 /* set all flash to require erasing */
645 for (c
= flash_bank_list(); c
; c
= c
->next
)
647 for (i
= 0; i
< c
->num_sectors
; i
++)
649 c
->sectors
[i
].is_erased
= 0;
654 static const struct command_registration flash_exec_command_handlers
[] = {
657 .handler
= &handle_flash_probe_command
,
658 .mode
= COMMAND_EXEC
,
660 .help
= "identify flash bank",
664 .handler
= &handle_flash_info_command
,
665 .mode
= COMMAND_EXEC
,
667 .help
= "print bank information",
670 .name
= "erase_check",
671 .handler
= &handle_flash_erase_check_command
,
672 .mode
= COMMAND_EXEC
,
674 .help
= "check erase state of sectors",
677 .name
= "protect_check",
678 .handler
= &handle_flash_protect_check_command
,
679 .mode
= COMMAND_EXEC
,
681 .help
= "check protection state of sectors",
684 .name
= "erase_sector",
685 .handler
= &handle_flash_erase_command
,
686 .mode
= COMMAND_EXEC
,
687 .usage
= "<bank> <first> <last>",
688 .help
= "erase sectors",
691 .name
= "erase_address",
692 .handler
= &handle_flash_erase_address_command
,
693 .mode
= COMMAND_EXEC
,
694 .usage
= "<address> <length>",
695 .help
= "erase address range",
700 .handler
= &handle_flash_fill_command
,
701 .mode
= COMMAND_EXEC
,
702 .usage
= "<address> <word_pattern> <count>",
703 .help
= "fill with pattern (no autoerase)",
707 .handler
= &handle_flash_fill_command
,
708 .mode
= COMMAND_EXEC
,
709 .usage
= "<address> <halfword_pattern> <count>",
710 .help
= "fill with pattern",
714 .handler
= &handle_flash_fill_command
,
715 .mode
= COMMAND_EXEC
,
716 .usage
= "<address> <byte_pattern> <count>",
717 .help
= "fill with pattern",
721 .name
= "write_bank",
722 .handler
= &handle_flash_write_bank_command
,
723 .mode
= COMMAND_EXEC
,
724 .usage
= "<bank> <file> <offset>",
725 .help
= "write binary data",
728 .name
= "write_image",
729 .handler
= &handle_flash_write_image_command
,
730 .mode
= COMMAND_EXEC
,
731 .usage
= "[erase] [unlock] <file> [offset] [type]",
732 .help
= "write an image to flash"
736 .handler
= &handle_flash_protect_command
,
737 .mode
= COMMAND_EXEC
,
738 .usage
= "<bank> <first> <last> <on | off>",
739 .help
= "set protection of sectors",
741 COMMAND_REGISTRATION_DONE
744 int flash_init_drivers(struct command_context
*cmd_ctx
)
746 if (!flash_bank_list())
749 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
750 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
754 COMMAND_HANDLER(handle_flash_bank_command
)
758 LOG_ERROR("usage: flash bank <name> <driver> "
759 "<base> <size> <chip_width> <bus_width>");
760 return ERROR_COMMAND_SYNTAX_ERROR
;
762 // save bank name and advance arguments for compatibility
763 const char *bank_name
= *CMD_ARGV
++;
766 struct target
*target
;
767 if ((target
= get_target(CMD_ARGV
[5])) == NULL
)
769 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
773 const char *driver_name
= CMD_ARGV
[0];
774 struct flash_driver
*driver
= flash_driver_find_by_name(driver_name
);
777 /* no matching flash driver found */
778 LOG_ERROR("flash driver '%s' not found", driver_name
);
782 /* register flash specific commands */
783 if (NULL
!= driver
->commands
)
785 int retval
= register_commands(CMD_CTX
, NULL
,
787 if (ERROR_OK
!= retval
)
789 LOG_ERROR("couldn't register '%s' commands",
795 struct flash_bank
*c
= malloc(sizeof(*c
));
796 c
->name
= strdup(bank_name
);
799 c
->driver_priv
= NULL
;
800 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], c
->base
);
801 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], c
->size
);
802 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], c
->chip_width
);
803 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[4], c
->bus_width
);
809 retval
= CALL_COMMAND_HANDLER(driver
->flash_bank_command
, c
);
810 if (ERROR_OK
!= retval
)
812 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32
,
813 driver_name
, c
->base
);
823 COMMAND_HANDLER(handle_flash_banks_command
)
826 return ERROR_INVALID_ARGUMENTS
;
829 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++)
831 LOG_USER("#%u: %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", "
832 "buswidth %u, chipwidth %u", n
,
833 p
->driver
->name
, p
->base
, p
->size
,
834 p
->bus_width
, p
->chip_width
);
839 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
843 Jim_WrongNumArgs(interp
, 1, argv
,
844 "no arguments to 'flash list' command");
848 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
850 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
)
852 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
854 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "name", -1));
855 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, p
->driver
->name
, -1));
856 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "base", -1));
857 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->base
));
858 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "size", -1));
859 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->size
));
860 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "bus_width", -1));
861 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->bus_width
));
862 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "chip_width", -1));
863 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->chip_width
));
865 Jim_ListAppendElement(interp
, list
, elem
);
868 Jim_SetResult(interp
, list
);
874 COMMAND_HANDLER(handle_flash_init_command
)
877 return ERROR_COMMAND_SYNTAX_ERROR
;
879 static bool flash_initialized
= false;
880 if (flash_initialized
)
882 LOG_INFO("'flash init' has already been called");
885 flash_initialized
= true;
887 LOG_DEBUG("Initializing flash devices...");
888 return flash_init_drivers(CMD_CTX
);
891 static const struct command_registration flash_config_command_handlers
[] = {
894 .handler
= &handle_flash_bank_command
,
895 .mode
= COMMAND_CONFIG
,
896 .usage
= "<name> <driver> <base> <size> "
897 "<chip_width> <bus_width> <target> "
898 "[driver_options ...]",
899 .help
= "Define a new bank with the given name, "
900 "using the specified NOR flash driver.",
904 .mode
= COMMAND_CONFIG
,
905 .handler
= &handle_flash_init_command
,
906 .help
= "initialize flash devices",
911 .handler
= &handle_flash_banks_command
,
912 .help
= "return readable information about the flash banks",
917 .jim_handler
= &jim_flash_list
,
918 .help
= "returns a list of details about the flash banks",
920 COMMAND_REGISTRATION_DONE
922 static const struct command_registration flash_command_handlers
[] = {
926 .help
= "NOR flash command group",
927 .chain
= flash_config_command_handlers
,
929 COMMAND_REGISTRATION_DONE
932 int flash_register_commands(struct command_context
*cmd_ctx
)
934 return register_commands(cmd_ctx
, NULL
, flash_command_handlers
);
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)