c13e26b8fd7828fe50055475e5c3f09dc36f86c9
[openocd.git] / src / xsvf / xsvf.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
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. *
9 * *
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. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "xsvf.h"
25
26 #include "jtag.h"
27 #include "command.h"
28 #include "log.h"
29
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <string.h>
36
37 #include <sys/time.h>
38 #include <time.h>
39
40 #define XSTATE_MAX_PATH (12)
41
42 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
43
44 int xsvf_fd = 0;
45
46 u8 *dr_out_buf; /* from host to device (TDI) */
47 u8 *dr_in_buf; /* from device to host (TDO) */
48 u8 *dr_in_mask;
49
50 int xsdrsize = 0;
51 int xruntest = 0; /* number of TCK cycles / microseconds */
52 int xrepeat = 0x20; /* number of XC9500 retries */
53
54 int xendir = 0;
55 int xenddr = 0;
56
57 enum tap_state xsvf_to_tap[] =
58 {
59 TAP_TLR, TAP_RTI,
60 TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD,
61 TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI,
62 };
63
64 int tap_to_xsvf[] =
65 {
66 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf
67 };
68
69
70 /* xsvf has it's own definition of a statemove. This needs
71 * to be handled according to the specs, which has nothing
72 * to do with the JTAG spec or OpenOCD as such.
73 *
74 * Implemented via jtag_add_pathmove().
75 */
76 void xsvf_add_statemove(enum tap_state state)
77 {
78 enum tap_state moves[7]; /* max # of transitions */
79 int i;
80 enum tap_state curstate = cmd_queue_cur_state;
81 u8 move = TAP_MOVE(cmd_queue_cur_state, state);
82
83 if ((state != TAP_TLR) && (state == cmd_queue_cur_state))
84 return;
85
86 for (i=0; i<7; i++)
87 {
88 int j = (move >> i) & 1;
89 if (j)
90 {
91 curstate = tap_transitions[curstate].high;
92 } else
93 {
94 curstate = tap_transitions[curstate].low;
95 }
96 moves[i] = curstate;
97 }
98
99 jtag_add_pathmove(7, moves);
100 }
101
102 int xsvf_register_commands(struct command_context_s *cmd_ctx)
103 {
104 register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,
105 COMMAND_EXEC, "run xsvf <file>");
106
107 return ERROR_OK;
108 }
109
110 int xsvf_read_buffer(int num_bits, int fd, u8* buf)
111 {
112 int num_bytes;
113
114 for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--)
115 {
116 if (read(fd, buf + num_bytes - 1, 1) < 0)
117 return ERROR_XSVF_EOF;
118 }
119
120 return ERROR_OK;
121 }
122
123 int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len)
124 {
125 char c;
126 unsigned char uc;
127
128 while ((read(fd, &c, 1) > 0) && (c == 0x12))
129 {
130 if (*path_len > max_path)
131 {
132 LOG_WARNING("XSTATE path longer than max_path");
133 break;
134 }
135 if (read(fd, &uc, 1) < 0)
136 {
137 return ERROR_XSVF_EOF;
138 }
139 path[(*path_len)++] = xsvf_to_tap[uc];
140 }
141
142 lseek(fd, -1, SEEK_CUR);
143
144 return ERROR_OK;
145 }
146
147 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
148 {
149 char c;
150 u8 buf4[4], buf2[2];
151 unsigned char uc, uc2;
152 unsigned int ui;
153 unsigned short us;
154
155 int do_abort = 0;
156 int unsupported = 0;
157 int tdo_mismatch = 0;
158
159 int runtest_requires_tck = 0;
160
161 int device = -1; /* use -1 to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device that should be affected */
162
163 if (argc < 2)
164 {
165 command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>");
166 return ERROR_OK;
167 }
168
169 if (strcmp(args[0], "plain") != 0)
170 {
171 device = strtoul(args[0], NULL, 0);
172 }
173
174 if ((xsvf_fd = open(args[1], O_RDONLY)) < 0)
175 {
176 command_print(cmd_ctx, "file %s not found", args[0]);
177 return ERROR_OK;
178 }
179
180 if ((argc > 2) && (strcmp(args[2], "virt2") == 0))
181 {
182 runtest_requires_tck = 1;
183 }
184
185 while (read(xsvf_fd, &c, 1) > 0)
186 {
187 switch (c)
188 {
189 case 0x00: /* XCOMPLETE */
190 LOG_DEBUG("XCOMPLETE");
191 if (jtag_execute_queue() != ERROR_OK)
192 {
193 tdo_mismatch = 1;
194 break;
195 }
196 break;
197 case 0x01: /* XTDOMASK */
198 LOG_DEBUG("XTDOMASK");
199 if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
200 do_abort = 1;
201 break;
202 case 0x02: /* XSIR */
203 LOG_DEBUG("XSIR");
204 if (read(xsvf_fd, &c, 1) < 0)
205 do_abort = 1;
206 else
207 {
208 u8 *ir_buf = malloc((c + 7) / 8);
209 if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK)
210 do_abort = 1;
211 else
212 {
213 scan_field_t field;
214 field.device = device;
215 field.num_bits = c;
216 field.out_value = ir_buf;
217 field.out_mask = NULL;
218 field.in_value = NULL;
219 field.in_check_value = NULL;
220 field.in_check_mask = NULL;
221 field.in_handler = NULL;
222 field.in_handler_priv = NULL;
223 if (device == -1)
224 jtag_add_plain_ir_scan(1, &field, TAP_PI);
225 else
226 jtag_add_ir_scan(1, &field, TAP_PI);
227 if (jtag_execute_queue() != ERROR_OK)
228 {
229 tdo_mismatch = 1;
230 free(ir_buf);
231 break;
232 }
233 if (xruntest)
234 {
235 if (runtest_requires_tck)
236 jtag_add_runtest(xruntest, xsvf_to_tap[xendir]);
237 else
238 {
239 xsvf_add_statemove(TAP_RTI);
240 jtag_add_sleep(xruntest);
241 xsvf_add_statemove(xsvf_to_tap[xendir]);
242 }
243 }
244 else if (xendir != 0xd) /* Pause-IR */
245 xsvf_add_statemove(xsvf_to_tap[xendir]);
246 }
247 free(ir_buf);
248 }
249 break;
250 case 0x03: /* XSDR */
251 LOG_DEBUG("XSDR");
252 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
253 do_abort = 1;
254 else
255 {
256 scan_field_t field;
257 field.device = device;
258 field.num_bits = xsdrsize;
259 field.out_value = dr_out_buf;
260 field.out_mask = NULL;
261 field.in_value = NULL;
262 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
263 if (device == -1)
264 jtag_add_plain_dr_scan(1, &field, TAP_PD);
265 else
266 jtag_add_dr_scan(1, &field, TAP_PD);
267 if (jtag_execute_queue() != ERROR_OK)
268 {
269 tdo_mismatch = 1;
270 break;
271 }
272 if (xruntest)
273 {
274 if (runtest_requires_tck)
275 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
276 else
277 {
278 xsvf_add_statemove(TAP_RTI);
279 jtag_add_sleep(xruntest);
280 xsvf_add_statemove(xsvf_to_tap[xenddr]);
281 }
282 }
283 else if (xendir != 0x6) /* Pause-DR */
284 xsvf_add_statemove(xsvf_to_tap[xenddr]);
285 }
286 break;
287 case 0x04: /* XRUNTEST */
288 LOG_DEBUG("XRUNTEST");
289 if (read(xsvf_fd, buf4, 4) < 0)
290 do_abort = 1;
291 else
292 {
293 xruntest = be_to_h_u32(buf4);
294 }
295 break;
296 case 0x07: /* XREPEAT */
297 LOG_DEBUG("XREPEAT");
298 if (read(xsvf_fd, &c, 1) < 0)
299 do_abort = 1;
300 else
301 {
302 xrepeat = c;
303 }
304 break;
305 case 0x08: /* XSDRSIZE */
306 LOG_DEBUG("XSDRSIZE");
307 if (read(xsvf_fd, buf4, 4) < 0)
308 do_abort = 1;
309 else
310 {
311 xsdrsize = be_to_h_u32(buf4);
312 free(dr_out_buf);
313 free(dr_in_buf);
314 free(dr_in_mask);
315 dr_out_buf = malloc((xsdrsize + 7) / 8);
316 dr_in_buf = malloc((xsdrsize + 7) / 8);
317 dr_in_mask = malloc((xsdrsize + 7) / 8);
318 }
319 break;
320 case 0x09: /* XSDRTDO */
321 LOG_DEBUG("XSDRTDO");
322 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
323 do_abort = 1;
324 else
325 {
326 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)
327 do_abort = 1;
328 else
329 {
330 scan_field_t field;
331 field.device = device;
332 field.num_bits = xsdrsize;
333 field.out_value = dr_out_buf;
334 field.out_mask = NULL;
335 field.in_value = NULL;
336 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
337 if (device == -1)
338 jtag_add_plain_dr_scan(1, &field, TAP_PD);
339 else
340 jtag_add_dr_scan(1, &field, TAP_PD);
341 if (jtag_execute_queue() != ERROR_OK)
342 {
343 tdo_mismatch = 1;
344 break;
345 }
346 if (xruntest)
347 {
348 if (runtest_requires_tck)
349 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
350 else
351 {
352 xsvf_add_statemove(TAP_RTI);
353 jtag_add_sleep(xruntest);
354 xsvf_add_statemove(xsvf_to_tap[xenddr]);
355 }
356 }
357 else if (xendir != 0x6) /* Pause-DR */
358 xsvf_add_statemove(xsvf_to_tap[xenddr]);
359 }
360 }
361 break;
362 case 0x0a: /* XSETDRMASKS */
363 LOG_ERROR("unsupported XSETSDRMASKS\n");
364 unsupported = 1;
365 break;
366 case 0x0b: /* XSDRINC */
367 LOG_ERROR("unsupported XSDRINC\n");
368 unsupported = 1;
369 break;
370 case 0x0c: /* XSDRB */
371 unsupported = 1;
372 break;
373 case 0x0d: /* XSDRC */
374 unsupported = 1;
375 break;
376 case 0x0e: /* XSDRE */
377 unsupported = 1;
378 break;
379 case 0x0f: /* XSDRTDOB */
380 unsupported = 1;
381 break;
382 case 0x10: /* XSDRTDOB */
383 unsupported = 1;
384 break;
385 case 0x11: /* XSDRTDOB */
386 unsupported = 1;
387 break;
388 case 0x12: /* XSTATE */
389 LOG_DEBUG("XSTATE");
390 if (read(xsvf_fd, &uc, 1) < 0)
391 do_abort = 1;
392 else
393 {
394 enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);
395 int path_len = 1;
396 path[0] = xsvf_to_tap[uc];
397 if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)
398 do_abort = 1;
399 else
400 {
401 jtag_add_pathmove(path_len, path);
402 }
403 free(path);
404 }
405 break;
406 case 0x13: /* XENDIR */
407 LOG_DEBUG("XENDIR");
408 if (read(xsvf_fd, &c, 1) < 0)
409 do_abort = 1;
410 else
411 {
412 if (c == 0)
413 xendir = 1;
414 else if (c == 1)
415 xendir = 0xd;
416 else
417 {
418 LOG_ERROR("unknown XENDIR endstate");
419 unsupported = 1;
420 }
421 }
422 break;
423 case 0x14: /* XENDDR */
424 LOG_DEBUG("XENDDR");
425 if (read(xsvf_fd, &c, 1) < 0)
426 do_abort = 1;
427 else
428 {
429 if (c == 0)
430 xenddr = 1;
431 else if (c == 1)
432 xenddr = 0x6;
433 else
434 {
435 LOG_ERROR("unknown XENDDR endstate");
436 unsupported = 1;
437 }
438 }
439 break;
440 case 0x15: /* XSIR2 */
441 LOG_DEBUG("XSIR2");
442 if (read(xsvf_fd, buf2, 2) < 0)
443 do_abort = 1;
444 else
445 {
446 u8 *ir_buf;
447 us = be_to_h_u16(buf2);
448 ir_buf = malloc((us + 7) / 8);
449 if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)
450 do_abort = 1;
451 else
452 {
453 scan_field_t field;
454 field.device = device;
455 field.num_bits = us;
456 field.out_value = ir_buf;
457 field.out_mask = NULL;
458 field.in_value = NULL;
459 field.in_check_value = NULL;
460 field.in_check_mask = NULL;
461 field.in_handler = NULL;
462 field.in_handler_priv = NULL;
463 if (device == -1)
464 jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);
465 else
466 jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);
467 }
468 free(ir_buf);
469 }
470 break;
471 case 0x16: /* XCOMMENT */
472 do
473 {
474 if (read(xsvf_fd, &c, 1) < 0)
475 {
476 do_abort = 1;
477 break;
478 }
479 } while (c != 0);
480 break;
481 case 0x17: /* XWAIT */
482 LOG_DEBUG("XWAIT");
483 if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))
484 do_abort = 1;
485 else
486 {
487 xsvf_add_statemove(xsvf_to_tap[uc]);
488 ui = be_to_h_u32(buf4);
489 jtag_add_sleep(ui);
490 xsvf_add_statemove(xsvf_to_tap[uc2]);
491 }
492 break;
493 default:
494 LOG_ERROR("unknown xsvf command (0x%2.2x)\n", c);
495 unsupported = 1;
496 }
497
498 if (do_abort || unsupported || tdo_mismatch)
499 break;
500 }
501
502 if (tdo_mismatch)
503 {
504 command_print(cmd_ctx, "TDO mismatch, aborting");
505 return ERROR_OK;
506 }
507
508 if (unsupported)
509 {
510 command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");
511 return ERROR_OK;
512 }
513
514 if (do_abort)
515 {
516 command_print(cmd_ctx, "premature end detected, aborting");
517 return ERROR_OK;
518 }
519
520 if (dr_out_buf)
521 free(dr_out_buf);
522
523 if (dr_in_buf)
524 free(dr_in_buf);
525
526 if (dr_in_mask)
527 free(dr_in_mask);
528
529 close(xsvf_fd);
530
531 command_print(cmd_ctx, "XSVF file programmed successfully");
532
533 return ERROR_OK;
534 }

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)