1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2009 by Simon Qian *
5 * SimonQian@SimonQian.com *
6 ***************************************************************************/
8 /* The specification for SVF is available here:
9 * http://www.asset-intertech.com/support/svf.pdf
10 * Below, this document is referred to as the "SVF spec".
12 * The specification for XSVF is available here:
13 * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf
14 * Below, this document is referred to as the "XSVF spec".
21 #include <jtag/jtag.h>
23 #include "helper/system.h"
24 #include <helper/time_support.h>
44 static const char *svf_command_name
[14] = {
68 static const char *svf_trst_mode_name
[4] = {
75 struct svf_statemove
{
78 uint32_t num_of_moves
;
83 * These paths are from the SVF specification for the STATE command, to be
84 * used when the STATE command only includes the final state. The first
85 * element of the path is the "from" (current) state, and the last one is
86 * the "to" (target) state.
88 * All specified paths are the shortest ones in the JTAG spec, and are thus
89 * not (!!) exact matches for the paths used elsewhere in OpenOCD. Note
90 * that PAUSE-to-PAUSE transitions all go through UPDATE and then CAPTURE,
91 * which has specific effects on the various registers; they are not NOPs.
93 * Paths to RESET are disabled here. As elsewhere in OpenOCD, and in XSVF
94 * and many SVF implementations, we don't want to risk missing that state.
95 * To get to RESET, always we ignore the current state.
97 static const struct svf_statemove svf_statemoves
[] = {
98 /* from to num_of_moves, paths[8] */
99 /* {TAP_RESET, TAP_RESET, 1, {TAP_RESET}}, */
100 {TAP_RESET
, TAP_IDLE
, 2, {TAP_RESET
, TAP_IDLE
} },
101 {TAP_RESET
, TAP_DRPAUSE
, 6, {TAP_RESET
, TAP_IDLE
, TAP_DRSELECT
,
102 TAP_DRCAPTURE
, TAP_DREXIT1
, TAP_DRPAUSE
} },
103 {TAP_RESET
, TAP_IRPAUSE
, 7, {TAP_RESET
, TAP_IDLE
, TAP_DRSELECT
,
104 TAP_IRSELECT
, TAP_IRCAPTURE
,
105 TAP_IREXIT1
, TAP_IRPAUSE
} },
107 /* {TAP_IDLE, TAP_RESET, 4, {TAP_IDLE,
108 * TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
109 {TAP_IDLE
, TAP_IDLE
, 1, {TAP_IDLE
} },
110 {TAP_IDLE
, TAP_DRPAUSE
, 5, {TAP_IDLE
, TAP_DRSELECT
, TAP_DRCAPTURE
,
111 TAP_DREXIT1
, TAP_DRPAUSE
} },
112 {TAP_IDLE
, TAP_IRPAUSE
, 6, {TAP_IDLE
, TAP_DRSELECT
, TAP_IRSELECT
,
113 TAP_IRCAPTURE
, TAP_IREXIT1
, TAP_IRPAUSE
} },
115 /* {TAP_DRPAUSE, TAP_RESET, 6, {TAP_DRPAUSE,
116 * TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
117 {TAP_DRPAUSE
, TAP_IDLE
, 4, {TAP_DRPAUSE
, TAP_DREXIT2
, TAP_DRUPDATE
,
119 {TAP_DRPAUSE
, TAP_DRPAUSE
, 7, {TAP_DRPAUSE
, TAP_DREXIT2
, TAP_DRUPDATE
,
120 TAP_DRSELECT
, TAP_DRCAPTURE
,
121 TAP_DREXIT1
, TAP_DRPAUSE
} },
122 {TAP_DRPAUSE
, TAP_IRPAUSE
, 8, {TAP_DRPAUSE
, TAP_DREXIT2
, TAP_DRUPDATE
,
123 TAP_DRSELECT
, TAP_IRSELECT
,
124 TAP_IRCAPTURE
, TAP_IREXIT1
, TAP_IRPAUSE
} },
126 /* {TAP_IRPAUSE, TAP_RESET, 6, {TAP_IRPAUSE,
127 * TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
128 {TAP_IRPAUSE
, TAP_IDLE
, 4, {TAP_IRPAUSE
, TAP_IREXIT2
, TAP_IRUPDATE
,
130 {TAP_IRPAUSE
, TAP_DRPAUSE
, 7, {TAP_IRPAUSE
, TAP_IREXIT2
, TAP_IRUPDATE
,
131 TAP_DRSELECT
, TAP_DRCAPTURE
,
132 TAP_DREXIT1
, TAP_DRPAUSE
} },
133 {TAP_IRPAUSE
, TAP_IRPAUSE
, 8, {TAP_IRPAUSE
, TAP_IREXIT2
, TAP_IRUPDATE
,
134 TAP_DRSELECT
, TAP_IRSELECT
,
135 TAP_IRCAPTURE
, TAP_IREXIT1
, TAP_IRPAUSE
} }
138 #define XXR_TDI (1 << 0)
139 #define XXR_TDO (1 << 1)
140 #define XXR_MASK (1 << 2)
141 #define XXR_SMASK (1 << 3)
142 struct svf_xxr_para
{
153 tap_state_t ir_end_state
;
154 tap_state_t dr_end_state
;
155 tap_state_t runtest_run_state
;
156 tap_state_t runtest_end_state
;
157 enum trst_mode trst_mode
;
159 struct svf_xxr_para hir_para
;
160 struct svf_xxr_para hdr_para
;
161 struct svf_xxr_para tir_para
;
162 struct svf_xxr_para tdr_para
;
163 struct svf_xxr_para sir_para
;
164 struct svf_xxr_para sdr_para
;
167 static struct svf_para svf_para
;
168 static const struct svf_para svf_para_init
= {
169 /* frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode */
170 0, TAP_IDLE
, TAP_IDLE
, TAP_IDLE
, TAP_IDLE
, TRST_Z
,
172 /* {len, data_mask, tdi, tdo, mask, smask}, */
173 {0, 0, NULL
, NULL
, NULL
, NULL
},
175 /* {len, data_mask, tdi, tdo, mask, smask}, */
176 {0, 0, NULL
, NULL
, NULL
, NULL
},
178 /* {len, data_mask, tdi, tdo, mask, smask}, */
179 {0, 0, NULL
, NULL
, NULL
, NULL
},
181 /* {len, data_mask, tdi, tdo, mask, smask}, */
182 {0, 0, NULL
, NULL
, NULL
, NULL
},
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
},
191 struct svf_check_tdo_para
{
192 int line_num
; /* used to record line number of the check operation */
193 /* so more information could be printed */
194 int enabled
; /* check is enabled or not */
195 int buffer_offset
; /* buffer_offset to buffers */
196 int bit_len
; /* bit length to check */
199 #define SVF_CHECK_TDO_PARA_SIZE 1024
200 static struct svf_check_tdo_para
*svf_check_tdo_para
;
201 static int svf_check_tdo_para_index
;
203 static int svf_read_command_from_file(FILE *fd
);
204 static int svf_check_tdo(void);
205 static int svf_add_check_para(uint8_t enabled
, int buffer_offset
, int bit_len
);
206 static int svf_run_command(struct command_context
*cmd_ctx
, char *cmd_str
);
207 static int svf_execute_tap(void);
210 static char *svf_read_line
;
211 static size_t svf_read_line_size
;
212 static char *svf_command_buffer
;
213 static size_t svf_command_buffer_size
;
214 static int svf_line_number
;
215 static int svf_getline(char **lineptr
, size_t *n
, FILE *stream
);
217 #define SVF_MAX_BUFFER_SIZE_TO_COMMIT (1024 * 1024)
218 static uint8_t *svf_tdi_buffer
, *svf_tdo_buffer
, *svf_mask_buffer
;
219 static int svf_buffer_index
, svf_buffer_size
;
220 static int svf_quiet
;
222 static int svf_ignore_error
;
224 /* Targeting particular tap */
225 static int svf_tap_is_specified
;
226 static int svf_set_padding(struct svf_xxr_para
*para
, int len
, unsigned char tdi
);
228 /* Progress Indicator */
229 static int svf_progress_enabled
;
230 static long svf_total_lines
;
231 static int svf_percentage
;
232 static int svf_last_printed_percentage
= -1;
235 * macro is used to print the svf hex buffer at desired debug level
236 * DEBUG, INFO, ERROR, USER
238 #define SVF_BUF_LOG(_lvl, _buf, _nbits, _desc) \
239 svf_hexbuf_print(LOG_LVL_##_lvl, __FILE__, __LINE__, __func__, _buf, _nbits, _desc)
241 static void svf_hexbuf_print(int dbg_lvl
, const char *file
, unsigned line
,
242 const char *function
, const uint8_t *buf
,
243 int bit_len
, const char *desc
)
246 int byte_len
= DIV_ROUND_UP(bit_len
, 8);
247 int msbits
= bit_len
% 8;
249 /* allocate 2 bytes per hex digit */
250 char *prbuf
= malloc((byte_len
* 2) + 2 + 1);
254 /* print correct number of bytes, mask excess bits where applicable */
255 uint8_t msb
= buf
[byte_len
- 1] & (msbits
? (1 << msbits
) - 1 : 0xff);
256 len
= sprintf(prbuf
, msbits
<= 4 ? "0x%01"PRIx8
: "0x%02"PRIx8
, msb
);
257 for (j
= byte_len
- 2; j
>= 0; j
--)
258 len
+= sprintf(prbuf
+ len
, "%02"PRIx8
, buf
[j
]);
260 log_printf_lf(dbg_lvl
, file
, line
, function
, "%8s = %s", desc
? desc
: " ", prbuf
);
265 static int svf_realloc_buffers(size_t len
)
269 if (svf_execute_tap() != ERROR_OK
)
272 ptr
= realloc(svf_tdi_buffer
, len
);
275 svf_tdi_buffer
= ptr
;
277 ptr
= realloc(svf_tdo_buffer
, len
);
280 svf_tdo_buffer
= ptr
;
282 ptr
= realloc(svf_mask_buffer
, len
);
285 svf_mask_buffer
= ptr
;
287 svf_buffer_size
= len
;
292 static void svf_free_xxd_para(struct svf_xxr_para
*para
)
309 int svf_add_statemove(tap_state_t state_to
)
311 tap_state_t state_from
= cmd_queue_cur_state
;
314 /* when resetting, be paranoid and ignore current state */
315 if (state_to
== TAP_RESET
) {
323 for (index_var
= 0; index_var
< ARRAY_SIZE(svf_statemoves
); index_var
++) {
324 if ((svf_statemoves
[index_var
].from
== state_from
)
325 && (svf_statemoves
[index_var
].to
== state_to
)) {
328 /* recorded path includes current state ... avoid
330 if (svf_statemoves
[index_var
].num_of_moves
> 1)
331 jtag_add_pathmove(svf_statemoves
[index_var
].num_of_moves
- 1,
332 svf_statemoves
[index_var
].paths
+ 1);
334 jtag_add_pathmove(svf_statemoves
[index_var
].num_of_moves
,
335 svf_statemoves
[index_var
].paths
);
339 LOG_ERROR("SVF: can not move to %s", tap_state_name(state_to
));
343 COMMAND_HANDLER(handle_svf_command
)
345 #define SVF_MIN_NUM_OF_OPTIONS 1
346 #define SVF_MAX_NUM_OF_OPTIONS 5
349 int64_t time_measure_ms
;
350 int time_measure_s
, time_measure_m
;
352 /* use NULL to indicate a "plain" svf file which accounts for
353 * any additional devices in the scan chain, otherwise the device
354 * that should be affected
356 struct jtag_tap
*tap
= NULL
;
358 if ((CMD_ARGC
< SVF_MIN_NUM_OF_OPTIONS
) || (CMD_ARGC
> SVF_MAX_NUM_OF_OPTIONS
))
359 return ERROR_COMMAND_SYNTAX_ERROR
;
361 /* parse command line */
364 svf_progress_enabled
= 0;
365 svf_ignore_error
= 0;
366 for (unsigned int i
= 0; i
< CMD_ARGC
; i
++) {
367 if (strcmp(CMD_ARGV
[i
], "-tap") == 0) {
368 tap
= jtag_tap_by_string(CMD_ARGV
[i
+1]);
370 command_print(CMD
, "Tap: %s unknown", CMD_ARGV
[i
+1]);
374 } else if ((strcmp(CMD_ARGV
[i
],
375 "quiet") == 0) || (strcmp(CMD_ARGV
[i
], "-quiet") == 0))
377 else if ((strcmp(CMD_ARGV
[i
], "nil") == 0) || (strcmp(CMD_ARGV
[i
], "-nil") == 0))
379 else if ((strcmp(CMD_ARGV
[i
],
380 "progress") == 0) || (strcmp(CMD_ARGV
[i
], "-progress") == 0))
381 svf_progress_enabled
= 1;
382 else if ((strcmp(CMD_ARGV
[i
],
383 "ignore_error") == 0) || (strcmp(CMD_ARGV
[i
], "-ignore_error") == 0))
384 svf_ignore_error
= 1;
386 svf_fd
= fopen(CMD_ARGV
[i
], "r");
389 command_print(CMD
, "open(\"%s\"): %s", CMD_ARGV
[i
], strerror(err
));
390 /* no need to free anything now */
391 return ERROR_COMMAND_SYNTAX_ERROR
;
393 LOG_USER("svf processing file: \"%s\"", CMD_ARGV
[i
]);
398 return ERROR_COMMAND_SYNTAX_ERROR
;
401 time_measure_ms
= timeval_ms();
405 svf_command_buffer_size
= 0;
407 svf_check_tdo_para_index
= 0;
408 svf_check_tdo_para
= malloc(sizeof(struct svf_check_tdo_para
) * SVF_CHECK_TDO_PARA_SIZE
);
409 if (!svf_check_tdo_para
) {
410 LOG_ERROR("not enough memory");
415 svf_buffer_index
= 0;
416 /* double the buffer size */
417 /* in case current command cannot be committed, and next command is a bit scan command */
418 /* here is 32K bits for this big scan command, it should be enough */
419 /* buffer will be reallocated if buffer size is not enough */
420 if (svf_realloc_buffers(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT
) != ERROR_OK
) {
425 memcpy(&svf_para
, &svf_para_init
, sizeof(svf_para
));
433 /* Tap is specified, set header/trailer paddings */
434 int header_ir_len
= 0, header_dr_len
= 0, trailer_ir_len
= 0, trailer_dr_len
= 0;
435 struct jtag_tap
*check_tap
;
437 svf_tap_is_specified
= 1;
439 for (check_tap
= jtag_all_taps(); check_tap
; check_tap
= check_tap
->next_tap
) {
440 if (check_tap
->abs_chain_position
< tap
->abs_chain_position
) {
442 header_ir_len
+= check_tap
->ir_length
;
444 } else if (check_tap
->abs_chain_position
> tap
->abs_chain_position
) {
446 trailer_ir_len
+= check_tap
->ir_length
;
452 if (svf_set_padding(&svf_para
.hdr_para
, header_dr_len
, 0) != ERROR_OK
) {
453 LOG_ERROR("failed to set data header");
457 /* HIR %d TDI (0xFF) */
458 if (svf_set_padding(&svf_para
.hir_para
, header_ir_len
, 0xFF) != ERROR_OK
) {
459 LOG_ERROR("failed to set instruction header");
464 if (svf_set_padding(&svf_para
.tdr_para
, trailer_dr_len
, 0) != ERROR_OK
) {
465 LOG_ERROR("failed to set data trailer");
469 /* TIR %d TDI (0xFF) */
470 if (svf_set_padding(&svf_para
.tir_para
, trailer_ir_len
, 0xFF) != ERROR_OK
) {
471 LOG_ERROR("failed to set instruction trailer");
476 if (svf_progress_enabled
) {
477 /* Count total lines in file. */
478 while (!feof(svf_fd
)) {
479 svf_getline(&svf_command_buffer
, &svf_command_buffer_size
, svf_fd
);
484 while (svf_read_command_from_file(svf_fd
) == ERROR_OK
) {
487 if (svf_progress_enabled
) {
488 svf_percentage
= ((svf_line_number
* 20) / svf_total_lines
) * 5;
489 if (svf_last_printed_percentage
!= svf_percentage
) {
490 LOG_USER_N("\r%d%% ", svf_percentage
);
491 svf_last_printed_percentage
= svf_percentage
;
495 if (svf_progress_enabled
) {
496 svf_percentage
= ((svf_line_number
* 20) / svf_total_lines
) * 5;
497 LOG_USER_N("%3d%% %s", svf_percentage
, svf_read_line
);
499 LOG_USER_N("%s", svf_read_line
);
502 if (svf_run_command(CMD_CTX
, svf_command_buffer
) != ERROR_OK
) {
503 LOG_ERROR("fail to run command at line %d", svf_line_number
);
510 if ((!svf_nil
) && (jtag_execute_queue() != ERROR_OK
))
512 else if (svf_check_tdo() != ERROR_OK
)
516 time_measure_ms
= timeval_ms() - time_measure_ms
;
517 time_measure_s
= time_measure_ms
/ 1000;
518 time_measure_ms
%= 1000;
519 time_measure_m
= time_measure_s
/ 60;
520 time_measure_s
%= 60;
521 if (time_measure_ms
< 1000)
523 "\r\nTime used: %dm%ds%" PRId64
"ms ",
534 free(svf_command_buffer
);
535 svf_command_buffer
= NULL
;
536 svf_command_buffer_size
= 0;
538 free(svf_check_tdo_para
);
539 svf_check_tdo_para
= NULL
;
540 svf_check_tdo_para_index
= 0;
542 free(svf_tdi_buffer
);
543 svf_tdi_buffer
= NULL
;
545 free(svf_tdo_buffer
);
546 svf_tdo_buffer
= NULL
;
548 free(svf_mask_buffer
);
549 svf_mask_buffer
= NULL
;
551 svf_buffer_index
= 0;
554 svf_free_xxd_para(&svf_para
.hdr_para
);
555 svf_free_xxd_para(&svf_para
.hir_para
);
556 svf_free_xxd_para(&svf_para
.tdr_para
);
557 svf_free_xxd_para(&svf_para
.tir_para
);
558 svf_free_xxd_para(&svf_para
.sdr_para
);
559 svf_free_xxd_para(&svf_para
.sir_para
);
563 "svf file programmed %s for %d commands with %d errors",
564 (svf_ignore_error
> 1) ? "unsuccessfully" : "successfully",
566 (svf_ignore_error
> 1) ? (svf_ignore_error
- 1) : 0);
568 command_print(CMD
, "svf file programmed failed");
570 svf_ignore_error
= 0;
574 static int svf_getline(char **lineptr
, size_t *n
, FILE *stream
)
576 #define MIN_CHUNK 16 /* Buffer is increased by this size each time as required */
581 *lineptr
= malloc(*n
);
586 (*lineptr
)[0] = fgetc(stream
);
587 while ((*lineptr
)[i
] != '\n') {
588 (*lineptr
)[++i
] = fgetc(stream
);
595 *lineptr
= realloc(*lineptr
, *n
);
601 return sizeof(*lineptr
);
604 #define SVFP_CMD_INC_CNT 1024
605 static int svf_read_command_from_file(FILE *fd
)
610 int cmd_ok
= 0, slash
= 0;
612 if (svf_getline(&svf_read_line
, &svf_read_line_size
, svf_fd
) <= 0)
615 ch
= svf_read_line
[0];
616 while (!cmd_ok
&& (ch
!= 0)) {
620 if (svf_getline(&svf_read_line
, &svf_read_line_size
, svf_fd
) <= 0)
628 if (svf_getline(&svf_read_line
, &svf_read_line_size
,
641 if (svf_getline(&svf_read_line
, &svf_read_line_size
, svf_fd
) <= 0)
647 /* Don't save '\r' and '\n' if no data is parsed */
652 /* The parsing code currently expects a space
653 * before parentheses -- "TDI (123)". Also a
654 * space afterwards -- "TDI (123) TDO(456)".
655 * But such spaces are optional... instead of
656 * parser updates, cope with that by adding the
659 * Ensure there are 3 bytes available, for:
660 * - current character
662 * - terminating NUL ('\0')
664 if (cmd_pos
+ 3 > svf_command_buffer_size
) {
665 svf_command_buffer
= realloc(svf_command_buffer
, cmd_pos
+ 3);
666 svf_command_buffer_size
= cmd_pos
+ 3;
667 if (!svf_command_buffer
) {
668 LOG_ERROR("not enough memory");
673 /* insert a space before '(' */
675 svf_command_buffer
[cmd_pos
++] = ' ';
677 svf_command_buffer
[cmd_pos
++] = (char)toupper(ch
);
679 /* insert a space after ')' */
681 svf_command_buffer
[cmd_pos
++] = ' ';
684 ch
= svf_read_line
[++i
];
688 svf_command_buffer
[cmd_pos
] = '\0';
694 static int svf_parse_cmd_string(char *str
, int len
, char **argus
, int *num_of_argu
)
696 int pos
= 0, num
= 0, space_found
= 1, in_bracket
= 0;
702 LOG_ERROR("fail to parse svf command");
712 if (!in_bracket
&& isspace((int) str
[pos
])) {
715 } else if (space_found
) {
716 argus
[num
++] = &str
[pos
];
732 bool svf_tap_state_is_stable(tap_state_t state
)
734 return (state
== TAP_RESET
) || (state
== TAP_IDLE
)
735 || (state
== TAP_DRPAUSE
) || (state
== TAP_IRPAUSE
);
738 static int svf_find_string_in_array(char *str
, char **strs
, int num_of_element
)
742 for (i
= 0; i
< num_of_element
; i
++) {
743 if (!strcmp(str
, strs
[i
]))
749 static int svf_adjust_array_length(uint8_t **arr
, int orig_bit_len
, int new_bit_len
)
751 int new_byte_len
= (new_bit_len
+ 7) >> 3;
753 if ((!*arr
) || (((orig_bit_len
+ 7) >> 3) < ((new_bit_len
+ 7) >> 3))) {
755 *arr
= calloc(1, new_byte_len
);
757 LOG_ERROR("not enough memory");
764 static int svf_set_padding(struct svf_xxr_para
*para
, int len
, unsigned char tdi
)
766 int error
= ERROR_OK
;
767 error
|= svf_adjust_array_length(¶
->tdi
, para
->len
, len
);
768 memset(para
->tdi
, tdi
, (len
+ 7) >> 3);
769 error
|= svf_adjust_array_length(¶
->tdo
, para
->len
, len
);
770 error
|= svf_adjust_array_length(¶
->mask
, para
->len
, len
);
772 para
->data_mask
= XXR_TDI
;
777 static int svf_copy_hexstring_to_binary(char *str
, uint8_t **bin
, int orig_bit_len
, int bit_len
)
779 int i
, str_len
= strlen(str
), str_hbyte_len
= (bit_len
+ 3) >> 2;
782 if (svf_adjust_array_length(bin
, orig_bit_len
, bit_len
) != ERROR_OK
) {
783 LOG_ERROR("fail to adjust length of array");
787 /* fill from LSB (end of str) to MSB (beginning of str) */
788 for (i
= 0; i
< str_hbyte_len
; i
++) {
790 while (str_len
> 0) {
793 /* Skip whitespace. The SVF specification (rev E) is
794 * deficient in terms of basic lexical issues like
795 * where whitespace is allowed. Long bitstrings may
796 * require line ends for correctness, since there is
797 * a hard limit on line length.
800 if ((ch
>= '0') && (ch
<= '9')) {
803 } else if ((ch
>= 'A') && (ch
<= 'F')) {
807 LOG_ERROR("invalid hex string");
818 (*bin
)[i
/ 2] |= ch
<< 4;
826 /* consume optional leading '0' MSBs or whitespace */
827 while (str_len
> 0 && ((str
[str_len
- 1] == '0')
828 || isspace((int) str
[str_len
- 1])))
831 /* check validity: we must have consumed everything */
832 if (str_len
> 0 || (ch
& ~((2 << ((bit_len
- 1) % 4)) - 1)) != 0) {
833 LOG_ERROR("value exceeds length");
840 static int svf_check_tdo(void)
842 int i
, len
, index_var
;
844 for (i
= 0; i
< svf_check_tdo_para_index
; i
++) {
845 index_var
= svf_check_tdo_para
[i
].buffer_offset
;
846 len
= svf_check_tdo_para
[i
].bit_len
;
847 if ((svf_check_tdo_para
[i
].enabled
)
848 && buf_cmp_mask(&svf_tdi_buffer
[index_var
], &svf_tdo_buffer
[index_var
],
849 &svf_mask_buffer
[index_var
], len
)) {
850 LOG_ERROR("tdo check error at line %d",
851 svf_check_tdo_para
[i
].line_num
);
852 SVF_BUF_LOG(ERROR
, &svf_tdi_buffer
[index_var
], len
, "READ");
853 SVF_BUF_LOG(ERROR
, &svf_tdo_buffer
[index_var
], len
, "WANT");
854 SVF_BUF_LOG(ERROR
, &svf_mask_buffer
[index_var
], len
, "MASK");
856 if (svf_ignore_error
== 0)
862 svf_check_tdo_para_index
= 0;
867 static int svf_add_check_para(uint8_t enabled
, int buffer_offset
, int bit_len
)
869 if (svf_check_tdo_para_index
>= SVF_CHECK_TDO_PARA_SIZE
) {
870 LOG_ERROR("toooooo many operation undone");
874 svf_check_tdo_para
[svf_check_tdo_para_index
].line_num
= svf_line_number
;
875 svf_check_tdo_para
[svf_check_tdo_para_index
].bit_len
= bit_len
;
876 svf_check_tdo_para
[svf_check_tdo_para_index
].enabled
= enabled
;
877 svf_check_tdo_para
[svf_check_tdo_para_index
].buffer_offset
= buffer_offset
;
878 svf_check_tdo_para_index
++;
883 static int svf_execute_tap(void)
885 if ((!svf_nil
) && (jtag_execute_queue() != ERROR_OK
))
887 else if (svf_check_tdo() != ERROR_OK
)
890 svf_buffer_index
= 0;
895 static int svf_run_command(struct command_context
*cmd_ctx
, char *cmd_str
)
897 char *argus
[256], command
;
898 int num_of_argu
= 0, i
;
907 struct svf_xxr_para
*xxr_para_tmp
;
908 uint8_t **pbuffer_tmp
;
909 struct scan_field field
;
911 tap_state_t
*path
= NULL
, state
;
912 /* flag padding commands skipped due to -tap command */
913 int padding_command_skipped
= 0;
915 if (svf_parse_cmd_string(cmd_str
, strlen(cmd_str
), argus
, &num_of_argu
) != ERROR_OK
)
918 /* NOTE: we're a bit loose here, because we ignore case in
919 * TAP state names (instead of insisting on uppercase).
922 command
= svf_find_string_in_array(argus
[0],
923 (char **)svf_command_name
, ARRAY_SIZE(svf_command_name
));
927 if (num_of_argu
!= 2) {
928 LOG_ERROR("invalid parameter of %s", argus
[0]);
932 i_tmp
= tap_state_by_name(argus
[1]);
934 if (svf_tap_state_is_stable(i_tmp
)) {
935 if (command
== ENDIR
) {
936 svf_para
.ir_end_state
= i_tmp
;
937 LOG_DEBUG("\tIR end_state = %s",
938 tap_state_name(i_tmp
));
940 svf_para
.dr_end_state
= i_tmp
;
941 LOG_DEBUG("\tDR end_state = %s",
942 tap_state_name(i_tmp
));
945 LOG_ERROR("%s: %s is not a stable state",
951 if ((num_of_argu
!= 1) && (num_of_argu
!= 3)) {
952 LOG_ERROR("invalid parameter of %s", argus
[0]);
955 if (num_of_argu
== 1) {
956 /* TODO: set jtag speed to full speed */
957 svf_para
.frequency
= 0;
959 if (strcmp(argus
[2], "HZ")) {
960 LOG_ERROR("HZ not found in FREQUENCY command");
963 if (svf_execute_tap() != ERROR_OK
)
965 svf_para
.frequency
= atof(argus
[1]);
966 /* TODO: set jtag speed to */
967 if (svf_para
.frequency
> 0) {
968 command_run_linef(cmd_ctx
,
970 (int)svf_para
.frequency
/ 1000);
971 LOG_DEBUG("\tfrequency = %f", svf_para
.frequency
);
976 if (svf_tap_is_specified
) {
977 padding_command_skipped
= 1;
980 xxr_para_tmp
= &svf_para
.hdr_para
;
983 if (svf_tap_is_specified
) {
984 padding_command_skipped
= 1;
987 xxr_para_tmp
= &svf_para
.hir_para
;
990 if (svf_tap_is_specified
) {
991 padding_command_skipped
= 1;
994 xxr_para_tmp
= &svf_para
.tdr_para
;
997 if (svf_tap_is_specified
) {
998 padding_command_skipped
= 1;
1001 xxr_para_tmp
= &svf_para
.tir_para
;
1004 xxr_para_tmp
= &svf_para
.sdr_para
;
1007 xxr_para_tmp
= &svf_para
.sir_para
;
1010 /* XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] */
1011 if ((num_of_argu
> 10) || (num_of_argu
% 2)) {
1012 LOG_ERROR("invalid parameter of %s", argus
[0]);
1015 i_tmp
= xxr_para_tmp
->len
;
1016 xxr_para_tmp
->len
= atoi(argus
[1]);
1017 /* If we are to enlarge the buffers, all parts of xxr_para_tmp
1018 * need to be freed */
1019 if (i_tmp
< xxr_para_tmp
->len
) {
1020 free(xxr_para_tmp
->tdi
);
1021 xxr_para_tmp
->tdi
= NULL
;
1022 free(xxr_para_tmp
->tdo
);
1023 xxr_para_tmp
->tdo
= NULL
;
1024 free(xxr_para_tmp
->mask
);
1025 xxr_para_tmp
->mask
= NULL
;
1026 free(xxr_para_tmp
->smask
);
1027 xxr_para_tmp
->smask
= NULL
;
1030 LOG_DEBUG("\tlength = %d", xxr_para_tmp
->len
);
1031 xxr_para_tmp
->data_mask
= 0;
1032 for (i
= 2; i
< num_of_argu
; i
+= 2) {
1033 if ((strlen(argus
[i
+ 1]) < 3) || (argus
[i
+ 1][0] != '(') ||
1034 (argus
[i
+ 1][strlen(argus
[i
+ 1]) - 1] != ')')) {
1035 LOG_ERROR("data section error");
1038 argus
[i
+ 1][strlen(argus
[i
+ 1]) - 1] = '\0';
1039 /* TDI, TDO, MASK, SMASK */
1040 if (!strcmp(argus
[i
], "TDI")) {
1042 pbuffer_tmp
= &xxr_para_tmp
->tdi
;
1043 xxr_para_tmp
->data_mask
|= XXR_TDI
;
1044 } else if (!strcmp(argus
[i
], "TDO")) {
1046 pbuffer_tmp
= &xxr_para_tmp
->tdo
;
1047 xxr_para_tmp
->data_mask
|= XXR_TDO
;
1048 } else if (!strcmp(argus
[i
], "MASK")) {
1050 pbuffer_tmp
= &xxr_para_tmp
->mask
;
1051 xxr_para_tmp
->data_mask
|= XXR_MASK
;
1052 } else if (!strcmp(argus
[i
], "SMASK")) {
1054 pbuffer_tmp
= &xxr_para_tmp
->smask
;
1055 xxr_para_tmp
->data_mask
|= XXR_SMASK
;
1057 LOG_ERROR("unknown parameter: %s", argus
[i
]);
1061 svf_copy_hexstring_to_binary(&argus
[i
+ 1][1], pbuffer_tmp
, i_tmp
,
1062 xxr_para_tmp
->len
)) {
1063 LOG_ERROR("fail to parse hex value");
1066 SVF_BUF_LOG(DEBUG
, *pbuffer_tmp
, xxr_para_tmp
->len
, argus
[i
]);
1068 /* If a command changes the length of the last scan of the same type and the
1069 * MASK parameter is absent, */
1070 /* the mask pattern used is all cares */
1071 if (!(xxr_para_tmp
->data_mask
& XXR_MASK
) && (i_tmp
!= xxr_para_tmp
->len
)) {
1072 /* MASK not defined and length changed */
1074 svf_adjust_array_length(&xxr_para_tmp
->mask
, i_tmp
,
1075 xxr_para_tmp
->len
)) {
1076 LOG_ERROR("fail to adjust length of array");
1079 buf_set_ones(xxr_para_tmp
->mask
, xxr_para_tmp
->len
);
1081 /* If TDO is absent, no comparison is needed, set the mask to 0 */
1082 if (!(xxr_para_tmp
->data_mask
& XXR_TDO
)) {
1083 if (!xxr_para_tmp
->tdo
) {
1085 svf_adjust_array_length(&xxr_para_tmp
->tdo
, i_tmp
,
1086 xxr_para_tmp
->len
)) {
1087 LOG_ERROR("fail to adjust length of array");
1091 if (!xxr_para_tmp
->mask
) {
1093 svf_adjust_array_length(&xxr_para_tmp
->mask
, i_tmp
,
1094 xxr_para_tmp
->len
)) {
1095 LOG_ERROR("fail to adjust length of array");
1099 memset(xxr_para_tmp
->mask
, 0, (xxr_para_tmp
->len
+ 7) >> 3);
1101 /* do scan if necessary */
1102 if (command
== SDR
) {
1103 /* check buffer size first, reallocate if necessary */
1104 i
= svf_para
.hdr_para
.len
+ svf_para
.sdr_para
.len
+
1105 svf_para
.tdr_para
.len
;
1106 if ((svf_buffer_size
- svf_buffer_index
) < ((i
+ 7) >> 3)) {
1107 /* reallocate buffer */
1108 if (svf_realloc_buffers(svf_buffer_index
+ ((i
+ 7) >> 3)) != ERROR_OK
) {
1109 LOG_ERROR("not enough memory");
1114 /* assemble dr data */
1116 buf_set_buf(svf_para
.hdr_para
.tdi
,
1118 &svf_tdi_buffer
[svf_buffer_index
],
1120 svf_para
.hdr_para
.len
);
1121 i
+= svf_para
.hdr_para
.len
;
1122 buf_set_buf(svf_para
.sdr_para
.tdi
,
1124 &svf_tdi_buffer
[svf_buffer_index
],
1126 svf_para
.sdr_para
.len
);
1127 i
+= svf_para
.sdr_para
.len
;
1128 buf_set_buf(svf_para
.tdr_para
.tdi
,
1130 &svf_tdi_buffer
[svf_buffer_index
],
1132 svf_para
.tdr_para
.len
);
1133 i
+= svf_para
.tdr_para
.len
;
1135 /* add check data */
1136 if (svf_para
.sdr_para
.data_mask
& XXR_TDO
) {
1137 /* assemble dr mask data */
1139 buf_set_buf(svf_para
.hdr_para
.mask
,
1141 &svf_mask_buffer
[svf_buffer_index
],
1143 svf_para
.hdr_para
.len
);
1144 i
+= svf_para
.hdr_para
.len
;
1145 buf_set_buf(svf_para
.sdr_para
.mask
,
1147 &svf_mask_buffer
[svf_buffer_index
],
1149 svf_para
.sdr_para
.len
);
1150 i
+= svf_para
.sdr_para
.len
;
1151 buf_set_buf(svf_para
.tdr_para
.mask
,
1153 &svf_mask_buffer
[svf_buffer_index
],
1155 svf_para
.tdr_para
.len
);
1157 /* assemble dr check data */
1159 buf_set_buf(svf_para
.hdr_para
.tdo
,
1161 &svf_tdo_buffer
[svf_buffer_index
],
1163 svf_para
.hdr_para
.len
);
1164 i
+= svf_para
.hdr_para
.len
;
1165 buf_set_buf(svf_para
.sdr_para
.tdo
,
1167 &svf_tdo_buffer
[svf_buffer_index
],
1169 svf_para
.sdr_para
.len
);
1170 i
+= svf_para
.sdr_para
.len
;
1171 buf_set_buf(svf_para
.tdr_para
.tdo
,
1173 &svf_tdo_buffer
[svf_buffer_index
],
1175 svf_para
.tdr_para
.len
);
1176 i
+= svf_para
.tdr_para
.len
;
1178 svf_add_check_para(1, svf_buffer_index
, i
);
1180 svf_add_check_para(0, svf_buffer_index
, i
);
1182 field
.out_value
= &svf_tdi_buffer
[svf_buffer_index
];
1183 field
.in_value
= (xxr_para_tmp
->data_mask
& XXR_TDO
) ? &svf_tdi_buffer
[svf_buffer_index
] : NULL
;
1185 /* NOTE: doesn't use SVF-specified state paths */
1186 jtag_add_plain_dr_scan(field
.num_bits
,
1189 svf_para
.dr_end_state
);
1192 svf_buffer_index
+= (i
+ 7) >> 3;
1193 } else if (command
== SIR
) {
1194 /* check buffer size first, reallocate if necessary */
1195 i
= svf_para
.hir_para
.len
+ svf_para
.sir_para
.len
+
1196 svf_para
.tir_para
.len
;
1197 if ((svf_buffer_size
- svf_buffer_index
) < ((i
+ 7) >> 3)) {
1198 if (svf_realloc_buffers(svf_buffer_index
+ ((i
+ 7) >> 3)) != ERROR_OK
) {
1199 LOG_ERROR("not enough memory");
1204 /* assemble ir data */
1206 buf_set_buf(svf_para
.hir_para
.tdi
,
1208 &svf_tdi_buffer
[svf_buffer_index
],
1210 svf_para
.hir_para
.len
);
1211 i
+= svf_para
.hir_para
.len
;
1212 buf_set_buf(svf_para
.sir_para
.tdi
,
1214 &svf_tdi_buffer
[svf_buffer_index
],
1216 svf_para
.sir_para
.len
);
1217 i
+= svf_para
.sir_para
.len
;
1218 buf_set_buf(svf_para
.tir_para
.tdi
,
1220 &svf_tdi_buffer
[svf_buffer_index
],
1222 svf_para
.tir_para
.len
);
1223 i
+= svf_para
.tir_para
.len
;
1225 /* add check data */
1226 if (svf_para
.sir_para
.data_mask
& XXR_TDO
) {
1227 /* assemble dr mask data */
1229 buf_set_buf(svf_para
.hir_para
.mask
,
1231 &svf_mask_buffer
[svf_buffer_index
],
1233 svf_para
.hir_para
.len
);
1234 i
+= svf_para
.hir_para
.len
;
1235 buf_set_buf(svf_para
.sir_para
.mask
,
1237 &svf_mask_buffer
[svf_buffer_index
],
1239 svf_para
.sir_para
.len
);
1240 i
+= svf_para
.sir_para
.len
;
1241 buf_set_buf(svf_para
.tir_para
.mask
,
1243 &svf_mask_buffer
[svf_buffer_index
],
1245 svf_para
.tir_para
.len
);
1247 /* assemble dr check data */
1249 buf_set_buf(svf_para
.hir_para
.tdo
,
1251 &svf_tdo_buffer
[svf_buffer_index
],
1253 svf_para
.hir_para
.len
);
1254 i
+= svf_para
.hir_para
.len
;
1255 buf_set_buf(svf_para
.sir_para
.tdo
,
1257 &svf_tdo_buffer
[svf_buffer_index
],
1259 svf_para
.sir_para
.len
);
1260 i
+= svf_para
.sir_para
.len
;
1261 buf_set_buf(svf_para
.tir_para
.tdo
,
1263 &svf_tdo_buffer
[svf_buffer_index
],
1265 svf_para
.tir_para
.len
);
1266 i
+= svf_para
.tir_para
.len
;
1268 svf_add_check_para(1, svf_buffer_index
, i
);
1270 svf_add_check_para(0, svf_buffer_index
, i
);
1272 field
.out_value
= &svf_tdi_buffer
[svf_buffer_index
];
1273 field
.in_value
= (xxr_para_tmp
->data_mask
& XXR_TDO
) ? &svf_tdi_buffer
[svf_buffer_index
] : NULL
;
1275 /* NOTE: doesn't use SVF-specified state paths */
1276 jtag_add_plain_ir_scan(field
.num_bits
,
1279 svf_para
.ir_end_state
);
1282 svf_buffer_index
+= (i
+ 7) >> 3;
1287 LOG_ERROR("PIO and PIOMAP are not supported");
1290 /* RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time
1291 * SEC]] [ENDSTATE end_state] */
1292 /* RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE
1294 if ((num_of_argu
< 3) || (num_of_argu
> 11)) {
1295 LOG_ERROR("invalid parameter of %s", argus
[0]);
1304 i_tmp
= tap_state_by_name(argus
[i
]);
1305 if (i_tmp
!= TAP_INVALID
) {
1306 if (svf_tap_state_is_stable(i_tmp
)) {
1307 svf_para
.runtest_run_state
= i_tmp
;
1309 /* When a run_state is specified, the new
1310 * run_state becomes the default end_state.
1312 svf_para
.runtest_end_state
= i_tmp
;
1313 LOG_DEBUG("\trun_state = %s", tap_state_name(i_tmp
));
1316 LOG_ERROR("%s: %s is not a stable state", argus
[0], tap_state_name(i_tmp
));
1321 /* run_count run_clk */
1322 if (((i
+ 2) <= num_of_argu
) && strcmp(argus
[i
+ 1], "SEC")) {
1323 if (!strcmp(argus
[i
+ 1], "TCK")) {
1324 /* clock source is TCK */
1325 run_count
= atoi(argus
[i
]);
1326 LOG_DEBUG("\trun_count@TCK = %d", run_count
);
1328 LOG_ERROR("%s not supported for clock", argus
[i
+ 1]);
1334 if (((i
+ 2) <= num_of_argu
) && !strcmp(argus
[i
+ 1], "SEC")) {
1335 min_time
= atof(argus
[i
]);
1336 LOG_DEBUG("\tmin_time = %fs", min_time
);
1339 /* MAXIMUM max_time SEC */
1340 if (((i
+ 3) <= num_of_argu
) &&
1341 !strcmp(argus
[i
], "MAXIMUM") && !strcmp(argus
[i
+ 2], "SEC")) {
1343 max_time
= atof(argus
[i
+ 1]);
1344 LOG_DEBUG("\tmax_time = %fs", max_time
);
1347 /* ENDSTATE end_state */
1348 if (((i
+ 2) <= num_of_argu
) && !strcmp(argus
[i
], "ENDSTATE")) {
1349 i_tmp
= tap_state_by_name(argus
[i
+ 1]);
1351 if (svf_tap_state_is_stable(i_tmp
)) {
1352 svf_para
.runtest_end_state
= i_tmp
;
1353 LOG_DEBUG("\tend_state = %s", tap_state_name(i_tmp
));
1355 LOG_ERROR("%s: %s is not a stable state", argus
[0], tap_state_name(i_tmp
));
1361 /* all parameter should be parsed */
1362 if (i
== num_of_argu
) {
1364 /* FIXME handle statemove failures */
1365 uint32_t min_usec
= 1000000 * min_time
;
1367 /* enter into run_state if necessary */
1368 if (cmd_queue_cur_state
!= svf_para
.runtest_run_state
)
1369 svf_add_statemove(svf_para
.runtest_run_state
);
1371 /* add clocks and/or min wait */
1372 if (run_count
> 0) {
1374 jtag_add_clocks(run_count
);
1379 jtag_add_sleep(min_usec
);
1382 /* move to end_state if necessary */
1383 if (svf_para
.runtest_end_state
!= svf_para
.runtest_run_state
)
1384 svf_add_statemove(svf_para
.runtest_end_state
);
1387 if (svf_para
.runtest_run_state
!= TAP_IDLE
) {
1388 LOG_ERROR("cannot runtest in %s state",
1389 tap_state_name(svf_para
.runtest_run_state
));
1394 jtag_add_runtest(run_count
, svf_para
.runtest_end_state
);
1397 LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed",
1404 /* STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state */
1405 if (num_of_argu
< 2) {
1406 LOG_ERROR("invalid parameter of %s", argus
[0]);
1409 if (num_of_argu
> 2) {
1410 /* STATE pathstate1 ... stable_state */
1411 path
= malloc((num_of_argu
- 1) * sizeof(tap_state_t
));
1413 LOG_ERROR("not enough memory");
1416 num_of_argu
--; /* num of path */
1417 i_tmp
= 1; /* path is from parameter 1 */
1418 for (i
= 0; i
< num_of_argu
; i
++, i_tmp
++) {
1419 path
[i
] = tap_state_by_name(argus
[i_tmp
]);
1420 if (path
[i
] == TAP_INVALID
) {
1421 LOG_ERROR("%s: %s is not a valid state", argus
[0], argus
[i_tmp
]);
1425 /* OpenOCD refuses paths containing TAP_RESET */
1426 if (path
[i
] == TAP_RESET
) {
1427 /* FIXME last state MUST be stable! */
1430 jtag_add_pathmove(i
, path
);
1434 num_of_argu
-= i
+ 1;
1438 if (num_of_argu
> 0) {
1439 /* execute last path if necessary */
1440 if (svf_tap_state_is_stable(path
[num_of_argu
- 1])) {
1441 /* last state MUST be stable state */
1443 jtag_add_pathmove(num_of_argu
, path
);
1444 LOG_DEBUG("\tmove to %s by path_move",
1445 tap_state_name(path
[num_of_argu
- 1]));
1447 LOG_ERROR("%s: %s is not a stable state",
1449 tap_state_name(path
[num_of_argu
- 1]));
1458 /* STATE stable_state */
1459 state
= tap_state_by_name(argus
[1]);
1460 if (svf_tap_state_is_stable(state
)) {
1461 LOG_DEBUG("\tmove to %s by svf_add_statemove",
1462 tap_state_name(state
));
1463 /* FIXME handle statemove failures */
1464 svf_add_statemove(state
);
1466 LOG_ERROR("%s: %s is not a stable state",
1467 argus
[0], tap_state_name(state
));
1473 /* TRST trst_mode */
1474 if (num_of_argu
!= 2) {
1475 LOG_ERROR("invalid parameter of %s", argus
[0]);
1478 if (svf_para
.trst_mode
!= TRST_ABSENT
) {
1479 if (svf_execute_tap() != ERROR_OK
)
1481 i_tmp
= svf_find_string_in_array(argus
[1],
1482 (char **)svf_trst_mode_name
,
1483 ARRAY_SIZE(svf_trst_mode_name
));
1487 jtag_add_reset(1, 0);
1492 jtag_add_reset(0, 0);
1497 LOG_ERROR("unknown TRST mode: %s", argus
[1]);
1500 svf_para
.trst_mode
= i_tmp
;
1501 LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name
[svf_para
.trst_mode
]);
1503 LOG_ERROR("can not accept TRST command if trst_mode is ABSENT");
1508 LOG_ERROR("invalid svf command: %s", argus
[0]);
1513 if (padding_command_skipped
)
1514 LOG_USER("(Above Padding command skipped, as per -tap argument)");
1517 if (debug_level
>= LOG_LVL_DEBUG
) {
1518 /* for convenient debugging, execute tap if possible */
1519 if ((svf_buffer_index
> 0) &&
1520 (((command
!= STATE
) && (command
!= RUNTEST
)) ||
1521 ((command
== STATE
) && (num_of_argu
== 2)))) {
1522 if (svf_execute_tap() != ERROR_OK
)
1525 /* output debug info */
1526 if ((command
== SIR
) || (command
== SDR
))
1527 SVF_BUF_LOG(DEBUG
, svf_tdi_buffer
, svf_check_tdo_para
[0].bit_len
, "TDO read");
1530 /* for fast executing, execute tap if necessary */
1531 /* half of the buffer is for the next command */
1532 if (((svf_buffer_index
>= SVF_MAX_BUFFER_SIZE_TO_COMMIT
) ||
1533 (svf_check_tdo_para_index
>= SVF_CHECK_TDO_PARA_SIZE
/ 2)) &&
1534 (((command
!= STATE
) && (command
!= RUNTEST
)) ||
1535 ((command
== STATE
) && (num_of_argu
== 2))))
1536 return svf_execute_tap();
1542 static const struct command_registration svf_command_handlers
[] = {
1545 .handler
= handle_svf_command
,
1546 .mode
= COMMAND_EXEC
,
1547 .help
= "Runs a SVF file.",
1548 .usage
= "[-tap device.tap] <file> [quiet] [nil] [progress] [ignore_error]",
1550 COMMAND_REGISTRATION_DONE
1553 int svf_register_commands(struct command_context
*cmd_ctx
)
1555 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)