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

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)