1 /***************************************************************************
2 * Copyright (C) 2009 by Simon Qian *
3 * SimonQian@SimonQian.com *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
21 /* The specification for SVF is available here:
22 * http://www.asset-intertech.com/support/svf.pdf
23 * Below, this document is refered to as the "SVF spec".
25 * The specification for XSVF is available here:
26 * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf
27 * Below, this document is refered to as the "XSVF spec".
34 #include <jtag/jtag.h>
36 #include <helper/time_support.h>
56 static const char *svf_command_name
[14] = {
80 static const char *svf_trst_mode_name
[4] = {
87 struct svf_statemove
{
90 uint32_t num_of_moves
;
95 * These paths are from the SVF specification for the STATE command, to be
96 * used when the STATE command only includes the final state. The first
97 * element of the path is the "from" (current) state, and the last one is
98 * the "to" (target) state.
100 * All specified paths are the shortest ones in the JTAG spec, and are thus
101 * not (!!) exact matches for the paths used elsewhere in OpenOCD. Note
102 * that PAUSE-to-PAUSE transitions all go through UPDATE and then CAPTURE,
103 * which has specific effects on the various registers; they are not NOPs.
105 * Paths to RESET are disabled here. As elsewhere in OpenOCD, and in XSVF
106 * and many SVF implementations, we don't want to risk missing that state.
107 * To get to RESET, always we ignore the current state.
109 static const struct svf_statemove svf_statemoves
[] = {
110 /* from to num_of_moves, paths[8] */
111 /* {TAP_RESET, TAP_RESET, 1, {TAP_RESET}}, */
112 {TAP_RESET
, TAP_IDLE
, 2, {TAP_RESET
, TAP_IDLE
} },
113 {TAP_RESET
, TAP_DRPAUSE
, 6, {TAP_RESET
, TAP_IDLE
, TAP_DRSELECT
,
114 TAP_DRCAPTURE
, TAP_DREXIT1
, TAP_DRPAUSE
} },
115 {TAP_RESET
, TAP_IRPAUSE
, 7, {TAP_RESET
, TAP_IDLE
, TAP_DRSELECT
,
116 TAP_IRSELECT
, TAP_IRCAPTURE
,
117 TAP_IREXIT1
, TAP_IRPAUSE
} },
119 /* {TAP_IDLE, TAP_RESET, 4, {TAP_IDLE,
120 * TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
121 {TAP_IDLE
, TAP_IDLE
, 1, {TAP_IDLE
} },
122 {TAP_IDLE
, TAP_DRPAUSE
, 5, {TAP_IDLE
, TAP_DRSELECT
, TAP_DRCAPTURE
,
123 TAP_DREXIT1
, TAP_DRPAUSE
} },
124 {TAP_IDLE
, TAP_IRPAUSE
, 6, {TAP_IDLE
, TAP_DRSELECT
, TAP_IRSELECT
,
125 TAP_IRCAPTURE
, TAP_IREXIT1
, TAP_IRPAUSE
} },
127 /* {TAP_DRPAUSE, TAP_RESET, 6, {TAP_DRPAUSE,
128 * TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
129 {TAP_DRPAUSE
, TAP_IDLE
, 4, {TAP_DRPAUSE
, TAP_DREXIT2
, TAP_DRUPDATE
,
131 {TAP_DRPAUSE
, TAP_DRPAUSE
, 7, {TAP_DRPAUSE
, TAP_DREXIT2
, TAP_DRUPDATE
,
132 TAP_DRSELECT
, TAP_DRCAPTURE
,
133 TAP_DREXIT1
, TAP_DRPAUSE
} },
134 {TAP_DRPAUSE
, TAP_IRPAUSE
, 8, {TAP_DRPAUSE
, TAP_DREXIT2
, TAP_DRUPDATE
,
135 TAP_DRSELECT
, TAP_IRSELECT
,
136 TAP_IRCAPTURE
, TAP_IREXIT1
, TAP_IRPAUSE
} },
138 /* {TAP_IRPAUSE, TAP_RESET, 6, {TAP_IRPAUSE,
139 * TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
140 {TAP_IRPAUSE
, TAP_IDLE
, 4, {TAP_IRPAUSE
, TAP_IREXIT2
, TAP_IRUPDATE
,
142 {TAP_IRPAUSE
, TAP_DRPAUSE
, 7, {TAP_IRPAUSE
, TAP_IREXIT2
, TAP_IRUPDATE
,
143 TAP_DRSELECT
, TAP_DRCAPTURE
,
144 TAP_DREXIT1
, TAP_DRPAUSE
} },
145 {TAP_IRPAUSE
, TAP_IRPAUSE
, 8, {TAP_IRPAUSE
, TAP_IREXIT2
, TAP_IRUPDATE
,
146 TAP_DRSELECT
, TAP_IRSELECT
,
147 TAP_IRCAPTURE
, TAP_IREXIT1
, TAP_IRPAUSE
} }
150 #define XXR_TDI (1 << 0)
151 #define XXR_TDO (1 << 1)
152 #define XXR_MASK (1 << 2)
153 #define XXR_SMASK (1 << 3)
154 struct svf_xxr_para
{
165 tap_state_t ir_end_state
;
166 tap_state_t dr_end_state
;
167 tap_state_t runtest_run_state
;
168 tap_state_t runtest_end_state
;
169 enum trst_mode trst_mode
;
171 struct svf_xxr_para hir_para
;
172 struct svf_xxr_para hdr_para
;
173 struct svf_xxr_para tir_para
;
174 struct svf_xxr_para tdr_para
;
175 struct svf_xxr_para sir_para
;
176 struct svf_xxr_para sdr_para
;
179 static struct svf_para svf_para
;
180 static const struct svf_para svf_para_init
= {
181 /* frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode */
182 0, TAP_IDLE
, TAP_IDLE
, TAP_IDLE
, TAP_IDLE
, TRST_Z
,
184 /* {len, data_mask, tdi, tdo, mask, smask}, */
185 {0, 0, NULL
, NULL
, NULL
, NULL
},
187 /* {len, data_mask, tdi, tdo, mask, smask}, */
188 {0, 0, NULL
, NULL
, NULL
, NULL
},
190 /* {len, data_mask, tdi, tdo, mask, smask}, */
191 {0, 0, NULL
, NULL
, NULL
, NULL
},
193 /* {len, data_mask, tdi, tdo, mask, smask}, */
194 {0, 0, NULL
, NULL
, NULL
, NULL
},
196 /* {len, data_mask, tdi, tdo, mask, smask}, */
197 {0, 0, NULL
, NULL
, NULL
, NULL
},
199 /* {len, data_mask, tdi, tdo, mask, smask}, */
200 {0, 0, NULL
, NULL
, NULL
, NULL
},
203 struct svf_check_tdo_para
{
204 int line_num
; /* used to record line number of the check operation */
205 /* so more information could be printed */
206 int enabled
; /* check is enabled or not */
207 int buffer_offset
; /* buffer_offset to buffers */
208 int bit_len
; /* bit length to check */
211 #define SVF_CHECK_TDO_PARA_SIZE 1024
212 static struct svf_check_tdo_para
*svf_check_tdo_para
;
213 static int svf_check_tdo_para_index
;
215 static int svf_read_command_from_file(FILE *fd
);
216 static int svf_check_tdo(void);
217 static int svf_add_check_para(uint8_t enabled
, int buffer_offset
, int bit_len
);
218 static int svf_run_command(struct command_context
*cmd_ctx
, char *cmd_str
);
221 static char *svf_read_line
;
222 static size_t svf_read_line_size
;
223 static char *svf_command_buffer
;
224 static size_t svf_command_buffer_size
;
225 static int svf_line_number
= 1;
226 static int svf_getline(char **lineptr
, size_t *n
, FILE *stream
);
228 #define SVF_MAX_BUFFER_SIZE_TO_COMMIT (1024 * 1024)
229 static uint8_t *svf_tdi_buffer
, *svf_tdo_buffer
, *svf_mask_buffer
;
230 static int svf_buffer_index
, svf_buffer_size
;
231 static int svf_quiet
;
234 /* Targetting particular tap */
235 static int svf_tap_is_specified
;
236 static int svf_set_padding(struct svf_xxr_para
*para
, int len
, unsigned char tdi
);
238 /* Progress Indicator */
239 static int svf_progress_enabled
;
240 static long svf_total_lines
;
241 static int svf_percentage
;
242 static int svf_last_printed_percentage
= -1;
244 static int svf_realloc_buffers(size_t len
)
248 ptr
= realloc(svf_tdi_buffer
, len
);
251 svf_tdi_buffer
= ptr
;
253 ptr
= realloc(svf_tdo_buffer
, len
);
256 svf_tdo_buffer
= ptr
;
258 ptr
= realloc(svf_mask_buffer
, len
);
261 svf_mask_buffer
= ptr
;
263 svf_buffer_size
= len
;
268 static void svf_free_xxd_para(struct svf_xxr_para
*para
)
271 if (para
->tdi
!= NULL
) {
275 if (para
->tdo
!= NULL
) {
279 if (para
->mask
!= NULL
) {
283 if (para
->smask
!= NULL
) {
290 static unsigned svf_get_mask_u32(int bitlen
)
296 else if (bitlen
>= 32)
297 bitmask
= 0xFFFFFFFF;
299 bitmask
= (1 << bitlen
) - 1;
304 int svf_add_statemove(tap_state_t state_to
)
306 tap_state_t state_from
= cmd_queue_cur_state
;
309 /* when resetting, be paranoid and ignore current state */
310 if (state_to
== TAP_RESET
) {
318 for (index_var
= 0; index_var
< ARRAY_SIZE(svf_statemoves
); index_var
++) {
319 if ((svf_statemoves
[index_var
].from
== state_from
)
320 && (svf_statemoves
[index_var
].to
== state_to
)) {
323 /* recorded path includes current state ... avoid
325 if (svf_statemoves
[index_var
].num_of_moves
> 1)
326 jtag_add_pathmove(svf_statemoves
[index_var
].num_of_moves
- 1,
327 svf_statemoves
[index_var
].paths
+ 1);
329 jtag_add_pathmove(svf_statemoves
[index_var
].num_of_moves
,
330 svf_statemoves
[index_var
].paths
);
334 LOG_ERROR("SVF: can not move to %s", tap_state_name(state_to
));
338 COMMAND_HANDLER(handle_svf_command
)
340 #define SVF_MIN_NUM_OF_OPTIONS 1
341 #define SVF_MAX_NUM_OF_OPTIONS 5
344 long long time_measure_ms
;
345 int time_measure_s
, time_measure_m
;
347 /* use NULL to indicate a "plain" svf file which accounts for
348 * any additional devices in the scan chain, otherwise the device
349 * that should be affected
351 struct jtag_tap
*tap
= NULL
;
353 if ((CMD_ARGC
< SVF_MIN_NUM_OF_OPTIONS
) || (CMD_ARGC
> SVF_MAX_NUM_OF_OPTIONS
))
354 return ERROR_COMMAND_SYNTAX_ERROR
;
356 /* parse command line */
359 for (unsigned int i
= 0; i
< CMD_ARGC
; i
++) {
360 if (strcmp(CMD_ARGV
[i
], "-tap") == 0) {
361 tap
= jtag_tap_by_string(CMD_ARGV
[i
+1]);
363 command_print(CMD_CTX
, "Tap: %s unknown", CMD_ARGV
[i
+1]);
367 } else if ((strcmp(CMD_ARGV
[i
],
368 "quiet") == 0) || (strcmp(CMD_ARGV
[i
], "-quiet") == 0))
370 else if ((strcmp(CMD_ARGV
[i
], "nil") == 0) || (strcmp(CMD_ARGV
[i
], "-nil") == 0))
372 else if ((strcmp(CMD_ARGV
[i
],
373 "progress") == 0) || (strcmp(CMD_ARGV
[i
], "-progress") == 0))
374 svf_progress_enabled
= 1;
376 svf_fd
= fopen(CMD_ARGV
[i
], "r");
377 if (svf_fd
== NULL
) {
379 command_print(CMD_CTX
, "open(\"%s\"): %s", CMD_ARGV
[i
], strerror(err
));
380 /* no need to free anything now */
381 return ERROR_COMMAND_SYNTAX_ERROR
;
383 LOG_USER("svf processing file: \"%s\"", CMD_ARGV
[i
]);
388 return ERROR_COMMAND_SYNTAX_ERROR
;
391 time_measure_ms
= timeval_ms();
395 svf_command_buffer_size
= 0;
397 svf_check_tdo_para_index
= 0;
398 svf_check_tdo_para
= malloc(sizeof(struct svf_check_tdo_para
) * SVF_CHECK_TDO_PARA_SIZE
);
399 if (NULL
== svf_check_tdo_para
) {
400 LOG_ERROR("not enough memory");
405 svf_buffer_index
= 0;
406 /* double the buffer size */
407 /* in case current command cannot be committed, and next command is a bit scan command */
408 /* here is 32K bits for this big scan command, it should be enough */
409 /* buffer will be reallocated if buffer size is not enough */
410 if (svf_realloc_buffers(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT
) != ERROR_OK
) {
415 memcpy(&svf_para
, &svf_para_init
, sizeof(svf_para
));
423 /* Tap is specified, set header/trailer paddings */
424 int header_ir_len
= 0, header_dr_len
= 0, trailer_ir_len
= 0, trailer_dr_len
= 0;
425 struct jtag_tap
*check_tap
;
427 svf_tap_is_specified
= 1;
429 for (check_tap
= jtag_all_taps(); check_tap
; check_tap
= check_tap
->next_tap
) {
430 if (check_tap
->abs_chain_position
< tap
->abs_chain_position
) {
432 header_ir_len
+= check_tap
->ir_length
;
434 } else if (check_tap
->abs_chain_position
> tap
->abs_chain_position
) {
436 trailer_ir_len
+= check_tap
->ir_length
;
442 if (ERROR_OK
!= svf_set_padding(&svf_para
.hdr_para
, header_dr_len
, 0)) {
443 LOG_ERROR("failed to set data header");
447 /* HIR %d TDI (0xFF) */
448 if (ERROR_OK
!= svf_set_padding(&svf_para
.hir_para
, header_ir_len
, 0xFF)) {
449 LOG_ERROR("failed to set instruction header");
454 if (ERROR_OK
!= svf_set_padding(&svf_para
.tdr_para
, trailer_dr_len
, 0)) {
455 LOG_ERROR("failed to set data trailer");
459 /* TIR %d TDI (0xFF) */
460 if (ERROR_OK
!= svf_set_padding(&svf_para
.tir_para
, trailer_ir_len
, 0xFF)) {
461 LOG_ERROR("failed to set instruction trailer");
466 if (svf_progress_enabled
) {
467 /* Count total lines in file. */
468 while (!feof(svf_fd
)) {
469 svf_getline(&svf_command_buffer
, &svf_command_buffer_size
, svf_fd
);
474 while (ERROR_OK
== svf_read_command_from_file(svf_fd
)) {
477 if (svf_progress_enabled
) {
478 svf_percentage
= ((svf_line_number
* 20) / svf_total_lines
) * 5;
479 if (svf_last_printed_percentage
!= svf_percentage
) {
480 LOG_USER_N("\r%d%% ", svf_percentage
);
481 svf_last_printed_percentage
= svf_percentage
;
485 if (svf_progress_enabled
) {
486 svf_percentage
= ((svf_line_number
* 20) / svf_total_lines
) * 5;
487 LOG_USER_N("%3d%% %s", svf_percentage
, svf_read_line
);
489 LOG_USER_N("%s", svf_read_line
);
492 if (ERROR_OK
!= svf_run_command(CMD_CTX
, svf_command_buffer
)) {
493 LOG_ERROR("fail to run command at line %d", svf_line_number
);
500 if ((!svf_nil
) && (ERROR_OK
!= jtag_execute_queue()))
502 else if (ERROR_OK
!= svf_check_tdo())
506 time_measure_ms
= timeval_ms() - time_measure_ms
;
507 time_measure_s
= time_measure_ms
/ 1000;
508 time_measure_ms
%= 1000;
509 time_measure_m
= time_measure_s
/ 60;
510 time_measure_s
%= 60;
511 if (time_measure_ms
< 1000)
512 command_print(CMD_CTX
,
513 "\r\nTime used: %dm%ds%lldms ",
524 if (svf_command_buffer
) {
525 free(svf_command_buffer
);
526 svf_command_buffer
= NULL
;
527 svf_command_buffer_size
= 0;
529 if (svf_check_tdo_para
) {
530 free(svf_check_tdo_para
);
531 svf_check_tdo_para
= NULL
;
532 svf_check_tdo_para_index
= 0;
534 if (svf_tdi_buffer
) {
535 free(svf_tdi_buffer
);
536 svf_tdi_buffer
= NULL
;
538 if (svf_tdo_buffer
) {
539 free(svf_tdo_buffer
);
540 svf_tdo_buffer
= NULL
;
542 if (svf_mask_buffer
) {
543 free(svf_mask_buffer
);
544 svf_mask_buffer
= NULL
;
546 svf_buffer_index
= 0;
549 svf_free_xxd_para(&svf_para
.hdr_para
);
550 svf_free_xxd_para(&svf_para
.hir_para
);
551 svf_free_xxd_para(&svf_para
.tdr_para
);
552 svf_free_xxd_para(&svf_para
.tir_para
);
553 svf_free_xxd_para(&svf_para
.sdr_para
);
554 svf_free_xxd_para(&svf_para
.sir_para
);
557 command_print(CMD_CTX
,
558 "svf file programmed successfully for %d commands",
561 command_print(CMD_CTX
, "svf file programmed failed");
566 static int svf_getline(char **lineptr
, size_t *n
, FILE *stream
)
568 #define MIN_CHUNK 16 /* Buffer is increased by this size each time as required */
571 if (*lineptr
== NULL
) {
573 *lineptr
= malloc(*n
);
578 (*lineptr
)[0] = fgetc(stream
);
579 while ((*lineptr
)[i
] != '\n') {
580 (*lineptr
)[++i
] = fgetc(stream
);
587 *lineptr
= realloc(*lineptr
, *n
);
593 return sizeof(*lineptr
);
596 #define SVFP_CMD_INC_CNT 1024
597 static int svf_read_command_from_file(FILE *fd
)
602 int cmd_ok
= 0, slash
= 0;
604 if (svf_getline(&svf_read_line
, &svf_read_line_size
, svf_fd
) <= 0)
607 ch
= svf_read_line
[0];
608 while (!cmd_ok
&& (ch
!= 0)) {
612 if (svf_getline(&svf_read_line
, &svf_read_line_size
, svf_fd
) <= 0)
620 if (svf_getline(&svf_read_line
, &svf_read_line_size
,
633 if (svf_getline(&svf_read_line
, &svf_read_line_size
, svf_fd
) <= 0)
638 /* Don't save '\r' and '\n' if no data is parsed */
642 /* The parsing code currently expects a space
643 * before parentheses -- "TDI (123)". Also a
644 * space afterwards -- "TDI (123) TDO(456)".
645 * But such spaces are optional... instead of
646 * parser updates, cope with that by adding the
649 * Ensure there are 3 bytes available, for:
650 * - current character
652 * - terminating NUL ('\0')
654 if (cmd_pos
+ 3 > svf_command_buffer_size
) {
655 svf_command_buffer
= realloc(svf_command_buffer
, cmd_pos
+ 3);
656 svf_command_buffer_size
= cmd_pos
+ 3;
657 if (svf_command_buffer
== NULL
) {
658 LOG_ERROR("not enough memory");
663 /* insert a space before '(' */
665 svf_command_buffer
[cmd_pos
++] = ' ';
667 svf_command_buffer
[cmd_pos
++] = (char)toupper(ch
);
669 /* insert a space after ')' */
671 svf_command_buffer
[cmd_pos
++] = ' ';
674 ch
= svf_read_line
[++i
];
678 svf_command_buffer
[cmd_pos
] = '\0';
684 static int svf_parse_cmd_string(char *str
, int len
, char **argus
, int *num_of_argu
)
686 int pos
= 0, num
= 0, space_found
= 1, in_bracket
= 0;
692 LOG_ERROR("fail to parse svf command");
702 if (!in_bracket
&& isspace((int) str
[pos
])) {
705 } else if (space_found
) {
706 argus
[num
++] = &str
[pos
];
719 bool svf_tap_state_is_stable(tap_state_t state
)
721 return (TAP_RESET
== state
) || (TAP_IDLE
== state
)
722 || (TAP_DRPAUSE
== state
) || (TAP_IRPAUSE
== state
);
725 static int svf_find_string_in_array(char *str
, char **strs
, int num_of_element
)
729 for (i
= 0; i
< num_of_element
; i
++) {
730 if (!strcmp(str
, strs
[i
]))
736 static int svf_adjust_array_length(uint8_t **arr
, int orig_bit_len
, int new_bit_len
)
738 int new_byte_len
= (new_bit_len
+ 7) >> 3;
740 if ((NULL
== *arr
) || (((orig_bit_len
+ 7) >> 3) < ((new_bit_len
+ 7) >> 3))) {
745 *arr
= malloc(new_byte_len
);
747 LOG_ERROR("not enough memory");
750 memset(*arr
, 0, new_byte_len
);
755 static int svf_set_padding(struct svf_xxr_para
*para
, int len
, unsigned char tdi
)
757 int error
= ERROR_OK
;
758 error
|= svf_adjust_array_length(¶
->tdi
, para
->len
, len
);
759 memset(para
->tdi
, tdi
, (len
+ 7) >> 3);
760 error
|= svf_adjust_array_length(¶
->tdo
, para
->len
, len
);
761 error
|= svf_adjust_array_length(¶
->mask
, para
->len
, len
);
763 para
->data_mask
= XXR_TDI
;
768 static int svf_copy_hexstring_to_binary(char *str
, uint8_t **bin
, int orig_bit_len
, int bit_len
)
770 int i
, str_len
= strlen(str
), str_hbyte_len
= (bit_len
+ 3) >> 2;
773 if (ERROR_OK
!= svf_adjust_array_length(bin
, orig_bit_len
, bit_len
)) {
774 LOG_ERROR("fail to adjust length of array");
778 /* fill from LSB (end of str) to MSB (beginning of str) */
779 for (i
= 0; i
< str_hbyte_len
; i
++) {
781 while (str_len
> 0) {
784 /* Skip whitespace. The SVF specification (rev E) is
785 * deficient in terms of basic lexical issues like
786 * where whitespace is allowed. Long bitstrings may
787 * require line ends for correctness, since there is
788 * a hard limit on line length.
791 if ((ch
>= '0') && (ch
<= '9')) {
794 } else if ((ch
>= 'A') && (ch
<= 'F')) {
798 LOG_ERROR("invalid hex string");
809 (*bin
)[i
/ 2] |= ch
<< 4;
817 /* consume optional leading '0' MSBs or whitespace */
818 while (str_len
> 0 && ((str
[str_len
- 1] == '0')
819 || isspace((int) str
[str_len
- 1])))
822 /* check validity: we must have consumed everything */
823 if (str_len
> 0 || (ch
& ~((2 << ((bit_len
- 1) % 4)) - 1)) != 0) {
824 LOG_ERROR("value execeeds length");
831 static int svf_check_tdo(void)
833 int i
, len
, index_var
;
835 for (i
= 0; i
< svf_check_tdo_para_index
; i
++) {
836 index_var
= svf_check_tdo_para
[i
].buffer_offset
;
837 len
= svf_check_tdo_para
[i
].bit_len
;
838 if ((svf_check_tdo_para
[i
].enabled
)
839 && buf_cmp_mask(&svf_tdi_buffer
[index_var
], &svf_tdo_buffer
[index_var
],
840 &svf_mask_buffer
[index_var
], len
)) {
842 unsigned received
, expected
, tapmask
;
843 bitmask
= svf_get_mask_u32(svf_check_tdo_para
[i
].bit_len
);
845 memcpy(&received
, svf_tdi_buffer
+ index_var
, sizeof(unsigned));
846 memcpy(&expected
, svf_tdo_buffer
+ index_var
, sizeof(unsigned));
847 memcpy(&tapmask
, svf_mask_buffer
+ index_var
, sizeof(unsigned));
848 LOG_ERROR("tdo check error at line %d",
849 svf_check_tdo_para
[i
].line_num
);
850 LOG_ERROR("read = 0x%X, want = 0x%X, mask = 0x%X",
857 svf_check_tdo_para_index
= 0;
862 static int svf_add_check_para(uint8_t enabled
, int buffer_offset
, int bit_len
)
864 if (svf_check_tdo_para_index
>= SVF_CHECK_TDO_PARA_SIZE
) {
865 LOG_ERROR("toooooo many operation undone");
869 svf_check_tdo_para
[svf_check_tdo_para_index
].line_num
= svf_line_number
;
870 svf_check_tdo_para
[svf_check_tdo_para_index
].bit_len
= bit_len
;
871 svf_check_tdo_para
[svf_check_tdo_para_index
].enabled
= enabled
;
872 svf_check_tdo_para
[svf_check_tdo_para_index
].buffer_offset
= buffer_offset
;
873 svf_check_tdo_para_index
++;
878 static int svf_execute_tap(void)
880 if ((!svf_nil
) && (ERROR_OK
!= jtag_execute_queue()))
882 else if (ERROR_OK
!= svf_check_tdo())
885 svf_buffer_index
= 0;
890 static int svf_run_command(struct command_context
*cmd_ctx
, char *cmd_str
)
892 char *argus
[256], command
;
893 int num_of_argu
= 0, i
;
902 struct svf_xxr_para
*xxr_para_tmp
;
903 uint8_t **pbuffer_tmp
;
904 struct scan_field field
;
906 tap_state_t
*path
= NULL
, state
;
907 /* flag padding commands skipped due to -tap command */
908 int padding_command_skipped
= 0;
910 if (ERROR_OK
!= svf_parse_cmd_string(cmd_str
, strlen(cmd_str
), argus
, &num_of_argu
))
913 /* NOTE: we're a bit loose here, because we ignore case in
914 * TAP state names (instead of insisting on uppercase).
917 command
= svf_find_string_in_array(argus
[0],
918 (char **)svf_command_name
, ARRAY_SIZE(svf_command_name
));
922 if (num_of_argu
!= 2) {
923 LOG_ERROR("invalid parameter of %s", argus
[0]);
927 i_tmp
= tap_state_by_name(argus
[1]);
929 if (svf_tap_state_is_stable(i_tmp
)) {
930 if (command
== ENDIR
) {
931 svf_para
.ir_end_state
= i_tmp
;
932 LOG_DEBUG("\tIR end_state = %s",
933 tap_state_name(i_tmp
));
935 svf_para
.dr_end_state
= i_tmp
;
936 LOG_DEBUG("\tDR end_state = %s",
937 tap_state_name(i_tmp
));
940 LOG_ERROR("%s: %s is not a stable state",
946 if ((num_of_argu
!= 1) && (num_of_argu
!= 3)) {
947 LOG_ERROR("invalid parameter of %s", argus
[0]);
950 if (1 == num_of_argu
) {
951 /* TODO: set jtag speed to full speed */
952 svf_para
.frequency
= 0;
954 if (strcmp(argus
[2], "HZ")) {
955 LOG_ERROR("HZ not found in FREQUENCY command");
958 if (ERROR_OK
!= svf_execute_tap())
960 svf_para
.frequency
= atof(argus
[1]);
961 /* TODO: set jtag speed to */
962 if (svf_para
.frequency
> 0) {
963 command_run_linef(cmd_ctx
,
965 (int)svf_para
.frequency
/ 1000);
966 LOG_DEBUG("\tfrequency = %f", svf_para
.frequency
);
971 if (svf_tap_is_specified
) {
972 padding_command_skipped
= 1;
975 xxr_para_tmp
= &svf_para
.hdr_para
;
978 if (svf_tap_is_specified
) {
979 padding_command_skipped
= 1;
982 xxr_para_tmp
= &svf_para
.hir_para
;
985 if (svf_tap_is_specified
) {
986 padding_command_skipped
= 1;
989 xxr_para_tmp
= &svf_para
.tdr_para
;
992 if (svf_tap_is_specified
) {
993 padding_command_skipped
= 1;
996 xxr_para_tmp
= &svf_para
.tir_para
;
999 xxr_para_tmp
= &svf_para
.sdr_para
;
1002 xxr_para_tmp
= &svf_para
.sir_para
;
1005 /* XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] */
1006 if ((num_of_argu
> 10) || (num_of_argu
% 2)) {
1007 LOG_ERROR("invalid parameter of %s", argus
[0]);
1010 i_tmp
= xxr_para_tmp
->len
;
1011 xxr_para_tmp
->len
= atoi(argus
[1]);
1012 LOG_DEBUG("\tlength = %d", xxr_para_tmp
->len
);
1013 xxr_para_tmp
->data_mask
= 0;
1014 for (i
= 2; i
< num_of_argu
; i
+= 2) {
1015 if ((strlen(argus
[i
+ 1]) < 3) || (argus
[i
+ 1][0] != '(') ||
1016 (argus
[i
+ 1][strlen(argus
[i
+ 1]) - 1] != ')')) {
1017 LOG_ERROR("data section error");
1020 argus
[i
+ 1][strlen(argus
[i
+ 1]) - 1] = '\0';
1021 /* TDI, TDO, MASK, SMASK */
1022 if (!strcmp(argus
[i
], "TDI")) {
1024 pbuffer_tmp
= &xxr_para_tmp
->tdi
;
1025 xxr_para_tmp
->data_mask
|= XXR_TDI
;
1026 } else if (!strcmp(argus
[i
], "TDO")) {
1028 pbuffer_tmp
= &xxr_para_tmp
->tdo
;
1029 xxr_para_tmp
->data_mask
|= XXR_TDO
;
1030 } else if (!strcmp(argus
[i
], "MASK")) {
1032 pbuffer_tmp
= &xxr_para_tmp
->mask
;
1033 xxr_para_tmp
->data_mask
|= XXR_MASK
;
1034 } else if (!strcmp(argus
[i
], "SMASK")) {
1036 pbuffer_tmp
= &xxr_para_tmp
->smask
;
1037 xxr_para_tmp
->data_mask
|= XXR_SMASK
;
1039 LOG_ERROR("unknow parameter: %s", argus
[i
]);
1043 svf_copy_hexstring_to_binary(&argus
[i
+ 1][1], pbuffer_tmp
, i_tmp
,
1044 xxr_para_tmp
->len
)) {
1045 LOG_ERROR("fail to parse hex value");
1048 LOG_DEBUG("\t%s = 0x%X", argus
[i
],
1049 (**(int **)pbuffer_tmp
) & svf_get_mask_u32(xxr_para_tmp
->len
));
1051 /* If a command changes the length of the last scan of the same type and the
1052 * MASK parameter is absent, */
1053 /* the mask pattern used is all cares */
1054 if (!(xxr_para_tmp
->data_mask
& XXR_MASK
) && (i_tmp
!= xxr_para_tmp
->len
)) {
1055 /* MASK not defined and length changed */
1057 svf_adjust_array_length(&xxr_para_tmp
->mask
, i_tmp
,
1058 xxr_para_tmp
->len
)) {
1059 LOG_ERROR("fail to adjust length of array");
1062 buf_set_ones(xxr_para_tmp
->mask
, xxr_para_tmp
->len
);
1064 /* If TDO is absent, no comparison is needed, set the mask to 0 */
1065 if (!(xxr_para_tmp
->data_mask
& XXR_TDO
)) {
1066 if (NULL
== xxr_para_tmp
->tdo
) {
1068 svf_adjust_array_length(&xxr_para_tmp
->tdo
, i_tmp
,
1069 xxr_para_tmp
->len
)) {
1070 LOG_ERROR("fail to adjust length of array");
1074 if (NULL
== xxr_para_tmp
->mask
) {
1076 svf_adjust_array_length(&xxr_para_tmp
->mask
, i_tmp
,
1077 xxr_para_tmp
->len
)) {
1078 LOG_ERROR("fail to adjust length of array");
1082 memset(xxr_para_tmp
->mask
, 0, (xxr_para_tmp
->len
+ 7) >> 3);
1084 /* do scan if necessary */
1085 if (SDR
== command
) {
1086 /* check buffer size first, reallocate if necessary */
1087 i
= svf_para
.hdr_para
.len
+ svf_para
.sdr_para
.len
+
1088 svf_para
.tdr_para
.len
;
1089 if ((svf_buffer_size
- svf_buffer_index
) < ((i
+ 7) >> 3)) {
1090 /* reallocate buffer */
1091 if (svf_realloc_buffers(svf_buffer_index
+ ((i
+ 7) >> 3)) != ERROR_OK
) {
1092 LOG_ERROR("not enough memory");
1097 /* assemble dr data */
1099 buf_set_buf(svf_para
.hdr_para
.tdi
,
1101 &svf_tdi_buffer
[svf_buffer_index
],
1103 svf_para
.hdr_para
.len
);
1104 i
+= svf_para
.hdr_para
.len
;
1105 buf_set_buf(svf_para
.sdr_para
.tdi
,
1107 &svf_tdi_buffer
[svf_buffer_index
],
1109 svf_para
.sdr_para
.len
);
1110 i
+= svf_para
.sdr_para
.len
;
1111 buf_set_buf(svf_para
.tdr_para
.tdi
,
1113 &svf_tdi_buffer
[svf_buffer_index
],
1115 svf_para
.tdr_para
.len
);
1116 i
+= svf_para
.tdr_para
.len
;
1118 /* add check data */
1119 if (svf_para
.sdr_para
.data_mask
& XXR_TDO
) {
1120 /* assemble dr mask data */
1122 buf_set_buf(svf_para
.hdr_para
.mask
,
1124 &svf_mask_buffer
[svf_buffer_index
],
1126 svf_para
.hdr_para
.len
);
1127 i
+= svf_para
.hdr_para
.len
;
1128 buf_set_buf(svf_para
.sdr_para
.mask
,
1130 &svf_mask_buffer
[svf_buffer_index
],
1132 svf_para
.sdr_para
.len
);
1133 i
+= svf_para
.sdr_para
.len
;
1134 buf_set_buf(svf_para
.tdr_para
.mask
,
1136 &svf_mask_buffer
[svf_buffer_index
],
1138 svf_para
.tdr_para
.len
);
1140 /* assemble dr check data */
1142 buf_set_buf(svf_para
.hdr_para
.tdo
,
1144 &svf_tdo_buffer
[svf_buffer_index
],
1146 svf_para
.hdr_para
.len
);
1147 i
+= svf_para
.hdr_para
.len
;
1148 buf_set_buf(svf_para
.sdr_para
.tdo
,
1150 &svf_tdo_buffer
[svf_buffer_index
],
1152 svf_para
.sdr_para
.len
);
1153 i
+= svf_para
.sdr_para
.len
;
1154 buf_set_buf(svf_para
.tdr_para
.tdo
,
1156 &svf_tdo_buffer
[svf_buffer_index
],
1158 svf_para
.tdr_para
.len
);
1159 i
+= svf_para
.tdr_para
.len
;
1161 svf_add_check_para(1, svf_buffer_index
, i
);
1163 svf_add_check_para(0, svf_buffer_index
, i
);
1165 field
.out_value
= &svf_tdi_buffer
[svf_buffer_index
];
1166 field
.in_value
= &svf_tdi_buffer
[svf_buffer_index
];
1168 /* NOTE: doesn't use SVF-specified state paths */
1169 jtag_add_plain_dr_scan(field
.num_bits
,
1172 svf_para
.dr_end_state
);
1175 svf_buffer_index
+= (i
+ 7) >> 3;
1176 } else if (SIR
== command
) {
1177 /* check buffer size first, reallocate if necessary */
1178 i
= svf_para
.hir_para
.len
+ svf_para
.sir_para
.len
+
1179 svf_para
.tir_para
.len
;
1180 if ((svf_buffer_size
- svf_buffer_index
) < ((i
+ 7) >> 3)) {
1181 if (svf_realloc_buffers(svf_buffer_index
+ ((i
+ 7) >> 3)) != ERROR_OK
) {
1182 LOG_ERROR("not enough memory");
1187 /* assemble ir data */
1189 buf_set_buf(svf_para
.hir_para
.tdi
,
1191 &svf_tdi_buffer
[svf_buffer_index
],
1193 svf_para
.hir_para
.len
);
1194 i
+= svf_para
.hir_para
.len
;
1195 buf_set_buf(svf_para
.sir_para
.tdi
,
1197 &svf_tdi_buffer
[svf_buffer_index
],
1199 svf_para
.sir_para
.len
);
1200 i
+= svf_para
.sir_para
.len
;
1201 buf_set_buf(svf_para
.tir_para
.tdi
,
1203 &svf_tdi_buffer
[svf_buffer_index
],
1205 svf_para
.tir_para
.len
);
1206 i
+= svf_para
.tir_para
.len
;
1208 /* add check data */
1209 if (svf_para
.sir_para
.data_mask
& XXR_TDO
) {
1210 /* assemble dr mask data */
1212 buf_set_buf(svf_para
.hir_para
.mask
,
1214 &svf_mask_buffer
[svf_buffer_index
],
1216 svf_para
.hir_para
.len
);
1217 i
+= svf_para
.hir_para
.len
;
1218 buf_set_buf(svf_para
.sir_para
.mask
,
1220 &svf_mask_buffer
[svf_buffer_index
],
1222 svf_para
.sir_para
.len
);
1223 i
+= svf_para
.sir_para
.len
;
1224 buf_set_buf(svf_para
.tir_para
.mask
,
1226 &svf_mask_buffer
[svf_buffer_index
],
1228 svf_para
.tir_para
.len
);
1230 /* assemble dr check data */
1232 buf_set_buf(svf_para
.hir_para
.tdo
,
1234 &svf_tdo_buffer
[svf_buffer_index
],
1236 svf_para
.hir_para
.len
);
1237 i
+= svf_para
.hir_para
.len
;
1238 buf_set_buf(svf_para
.sir_para
.tdo
,
1240 &svf_tdo_buffer
[svf_buffer_index
],
1242 svf_para
.sir_para
.len
);
1243 i
+= svf_para
.sir_para
.len
;
1244 buf_set_buf(svf_para
.tir_para
.tdo
,
1246 &svf_tdo_buffer
[svf_buffer_index
],
1248 svf_para
.tir_para
.len
);
1249 i
+= svf_para
.tir_para
.len
;
1251 svf_add_check_para(1, svf_buffer_index
, i
);
1253 svf_add_check_para(0, svf_buffer_index
, i
);
1255 field
.out_value
= &svf_tdi_buffer
[svf_buffer_index
];
1256 field
.in_value
= &svf_tdi_buffer
[svf_buffer_index
];
1258 /* NOTE: doesn't use SVF-specified state paths */
1259 jtag_add_plain_ir_scan(field
.num_bits
,
1262 svf_para
.ir_end_state
);
1265 svf_buffer_index
+= (i
+ 7) >> 3;
1270 LOG_ERROR("PIO and PIOMAP are not supported");
1274 /* RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time
1275 * SEC]] [ENDSTATE end_state] */
1276 /* RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE
1278 if ((num_of_argu
< 3) && (num_of_argu
> 11)) {
1279 LOG_ERROR("invalid parameter of %s", argus
[0]);
1288 i_tmp
= tap_state_by_name(argus
[i
]);
1289 if (i_tmp
!= TAP_INVALID
) {
1290 if (svf_tap_state_is_stable(i_tmp
)) {
1291 svf_para
.runtest_run_state
= i_tmp
;
1293 /* When a run_state is specified, the new
1294 * run_state becomes the default end_state.
1296 svf_para
.runtest_end_state
= i_tmp
;
1297 LOG_DEBUG("\trun_state = %s", tap_state_name(i_tmp
));
1300 LOG_ERROR("%s: %s is not a stable state", argus
[0], tap_state_name(i_tmp
));
1305 /* run_count run_clk */
1306 if (((i
+ 2) <= num_of_argu
) && strcmp(argus
[i
+ 1], "SEC")) {
1307 if (!strcmp(argus
[i
+ 1], "TCK")) {
1308 /* clock source is TCK */
1309 run_count
= atoi(argus
[i
]);
1310 LOG_DEBUG("\trun_count@TCK = %d", run_count
);
1312 LOG_ERROR("%s not supported for clock", argus
[i
+ 1]);
1318 if (((i
+ 2) <= num_of_argu
) && !strcmp(argus
[i
+ 1], "SEC")) {
1319 min_time
= atof(argus
[i
]);
1320 LOG_DEBUG("\tmin_time = %fs", min_time
);
1323 /* MAXIMUM max_time SEC */
1324 if (((i
+ 3) <= num_of_argu
) &&
1325 !strcmp(argus
[i
], "MAXIMUM") && !strcmp(argus
[i
+ 2], "SEC")) {
1327 max_time
= atof(argus
[i
+ 1]);
1328 LOG_DEBUG("\tmax_time = %fs", max_time
);
1331 /* ENDSTATE end_state */
1332 if (((i
+ 2) <= num_of_argu
) && !strcmp(argus
[i
], "ENDSTATE")) {
1333 i_tmp
= tap_state_by_name(argus
[i
+ 1]);
1335 if (svf_tap_state_is_stable(i_tmp
)) {
1336 svf_para
.runtest_end_state
= i_tmp
;
1337 LOG_DEBUG("\tend_state = %s", tap_state_name(i_tmp
));
1339 LOG_ERROR("%s: %s is not a stable state", argus
[0], tap_state_name(i_tmp
));
1345 /* all parameter should be parsed */
1346 if (i
== num_of_argu
) {
1348 /* FIXME handle statemove failures */
1349 uint32_t min_usec
= 1000000 * min_time
;
1351 /* enter into run_state if necessary */
1352 if (cmd_queue_cur_state
!= svf_para
.runtest_run_state
)
1353 svf_add_statemove(svf_para
.runtest_run_state
);
1355 /* add clocks and/or min wait */
1356 if (run_count
> 0) {
1358 jtag_add_clocks(run_count
);
1363 jtag_add_sleep(min_usec
);
1366 /* move to end_state if necessary */
1367 if (svf_para
.runtest_end_state
!= svf_para
.runtest_run_state
)
1368 svf_add_statemove(svf_para
.runtest_end_state
);
1371 if (svf_para
.runtest_run_state
!= TAP_IDLE
) {
1372 LOG_ERROR("cannot runtest in %s state",
1373 tap_state_name(svf_para
.runtest_run_state
));
1378 jtag_add_runtest(run_count
, svf_para
.runtest_end_state
);
1381 LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed",
1388 /* STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state */
1389 if (num_of_argu
< 2) {
1390 LOG_ERROR("invalid parameter of %s", argus
[0]);
1393 if (num_of_argu
> 2) {
1394 /* STATE pathstate1 ... stable_state */
1395 path
= malloc((num_of_argu
- 1) * sizeof(tap_state_t
));
1397 LOG_ERROR("not enough memory");
1400 num_of_argu
--; /* num of path */
1401 i_tmp
= 1; /* path is from parameter 1 */
1402 for (i
= 0; i
< num_of_argu
; i
++, i_tmp
++) {
1403 path
[i
] = tap_state_by_name(argus
[i_tmp
]);
1404 if (path
[i
] == TAP_INVALID
) {
1405 LOG_ERROR("%s: %s is not a valid state", argus
[0], argus
[i_tmp
]);
1409 /* OpenOCD refuses paths containing TAP_RESET */
1410 if (TAP_RESET
== path
[i
]) {
1411 /* FIXME last state MUST be stable! */
1414 jtag_add_pathmove(i
, path
);
1418 num_of_argu
-= i
+ 1;
1422 if (num_of_argu
> 0) {
1423 /* execute last path if necessary */
1424 if (svf_tap_state_is_stable(path
[num_of_argu
- 1])) {
1425 /* last state MUST be stable state */
1427 jtag_add_pathmove(num_of_argu
, path
);
1428 LOG_DEBUG("\tmove to %s by path_move",
1429 tap_state_name(path
[num_of_argu
- 1]));
1431 LOG_ERROR("%s: %s is not a stable state",
1433 tap_state_name(path
[num_of_argu
- 1]));
1442 /* STATE stable_state */
1443 state
= tap_state_by_name(argus
[1]);
1444 if (svf_tap_state_is_stable(state
)) {
1445 LOG_DEBUG("\tmove to %s by svf_add_statemove",
1446 tap_state_name(state
));
1447 /* FIXME handle statemove failures */
1448 svf_add_statemove(state
);
1450 LOG_ERROR("%s: %s is not a stable state",
1451 argus
[0], tap_state_name(state
));
1457 /* TRST trst_mode */
1458 if (num_of_argu
!= 2) {
1459 LOG_ERROR("invalid parameter of %s", argus
[0]);
1462 if (svf_para
.trst_mode
!= TRST_ABSENT
) {
1463 if (ERROR_OK
!= svf_execute_tap())
1465 i_tmp
= svf_find_string_in_array(argus
[1],
1466 (char **)svf_trst_mode_name
,
1467 ARRAY_SIZE(svf_trst_mode_name
));
1471 jtag_add_reset(1, 0);
1476 jtag_add_reset(0, 0);
1481 LOG_ERROR("unknown TRST mode: %s", argus
[1]);
1484 svf_para
.trst_mode
= i_tmp
;
1485 LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name
[svf_para
.trst_mode
]);
1487 LOG_ERROR("can not accpet TRST command if trst_mode is ABSENT");
1492 LOG_ERROR("invalid svf command: %s", argus
[0]);
1498 if (padding_command_skipped
)
1499 LOG_USER("(Above Padding command skipped, as per -tap argument)");
1502 if (debug_level
>= LOG_LVL_DEBUG
) {
1503 /* for convenient debugging, execute tap if possible */
1504 if ((svf_buffer_index
> 0) && \
1505 (((command
!= STATE
) && (command
!= RUNTEST
)) || \
1506 ((command
== STATE
) && (num_of_argu
== 2)))) {
1507 if (ERROR_OK
!= svf_execute_tap())
1510 /* output debug info */
1511 if ((SIR
== command
) || (SDR
== command
)) {
1513 memcpy(&read_value
, svf_tdi_buffer
, sizeof(int));
1514 /* in debug mode, data is from index 0 */
1515 int read_mask
= svf_get_mask_u32(svf_check_tdo_para
[0].bit_len
);
1516 LOG_DEBUG("\tTDO read = 0x%X", read_value
& read_mask
);
1520 /* for fast executing, execute tap if necessary */
1521 /* half of the buffer is for the next command */
1522 if (((svf_buffer_index
>= SVF_MAX_BUFFER_SIZE_TO_COMMIT
) ||
1523 (svf_check_tdo_para_index
>= SVF_CHECK_TDO_PARA_SIZE
/ 2)) && \
1524 (((command
!= STATE
) && (command
!= RUNTEST
)) || \
1525 ((command
== STATE
) && (num_of_argu
== 2))))
1526 return svf_execute_tap();
1532 static const struct command_registration svf_command_handlers
[] = {
1535 .handler
= handle_svf_command
,
1536 .mode
= COMMAND_EXEC
,
1537 .help
= "Runs a SVF file.",
1538 .usage
= "svf [-tap device.tap] <file> [quiet] [nil] [progress]",
1540 COMMAND_REGISTRATION_DONE
1543 int svf_register_commands(struct command_context
*cmd_ctx
)
1545 return register_commands(cmd_ctx
, NULL
, svf_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)