- added svn props for newly added files
[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 for (i=0; i<7; i++)
86 {
87 int j=(move>>i)&1;
88 if (j)
89 {
90 curstate=tap_transitions[curstate].high;
91 } else
92 {
93 curstate=tap_transitions[curstate].low;
94 }
95 moves[i]=curstate;
96 }
97 jtag_add_pathmove(7, moves);
98 }
99
100 int xsvf_register_commands(struct command_context_s *cmd_ctx)
101 {
102 register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,
103 COMMAND_EXEC, "run xsvf <file>");
104
105 return ERROR_OK;
106 }
107
108 int xsvf_read_buffer(int num_bits, int fd, u8* buf)
109 {
110 int num_bytes;
111
112 for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--)
113 {
114 if (read(fd, buf + num_bytes - 1, 1) < 0)
115 return ERROR_XSVF_EOF;
116 }
117
118 return ERROR_OK;
119 }
120
121 int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len)
122 {
123 char c;
124 unsigned char uc;
125
126 while ((read(fd, &c, 1) > 0) && (c == 0x12))
127 {
128 if (*path_len > max_path)
129 {
130 LOG_WARNING("XSTATE path longer than max_path");
131 break;
132 }
133 if (read(fd, &uc, 1) < 0)
134 {
135 return ERROR_XSVF_EOF;
136 }
137 path[(*path_len)++] = xsvf_to_tap[uc];
138 }
139
140 lseek(fd, -1, SEEK_CUR);
141
142 return ERROR_OK;
143 }
144
145 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
146 {
147 char c;
148 u8 buf4[4], buf2[2];
149 unsigned char uc, uc2;
150 unsigned int ui;
151 unsigned short us;
152
153 int do_abort = 0;
154 int unsupported = 0;
155 int tdo_mismatch = 0;
156
157 int runtest_requires_tck = 0;
158
159 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 */
160
161 if (argc < 2)
162 {
163 command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>");
164 return ERROR_OK;
165 }
166
167 if (strcmp(args[0], "plain") != 0)
168 {
169 device = strtoul(args[0], NULL, 0);
170 }
171
172 if ((xsvf_fd = open(args[1], O_RDONLY)) < 0)
173 {
174 command_print(cmd_ctx, "file %s not found", args[0]);
175 return ERROR_OK;
176 }
177
178 if ((argc > 2) && (strcmp(args[2], "virt2") == 0))
179 {
180 runtest_requires_tck = 1;
181 }
182
183 while (read(xsvf_fd, &c, 1) > 0)
184 {
185 switch (c)
186 {
187 case 0x00: /* XCOMPLETE */
188 LOG_DEBUG("XCOMPLETE");
189 if (jtag_execute_queue() != ERROR_OK)
190 {
191 tdo_mismatch = 1;
192 break;
193 }
194 break;
195 case 0x01: /* XTDOMASK */
196 LOG_DEBUG("XTDOMASK");
197 if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
198 do_abort = 1;
199 break;
200 case 0x02: /* XSIR */
201 LOG_DEBUG("XSIR");
202 if (read(xsvf_fd, &c, 1) < 0)
203 do_abort = 1;
204 else
205 {
206 u8 *ir_buf = malloc((c + 7) / 8);
207 if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK)
208 do_abort = 1;
209 else
210 {
211 scan_field_t field;
212 field.device = device;
213 field.num_bits = c;
214 field.out_value = ir_buf;
215 field.out_mask = NULL;
216 field.in_value = NULL;
217 field.in_check_value = NULL;
218 field.in_check_mask = NULL;
219 field.in_handler = NULL;
220 field.in_handler_priv = NULL;
221 if (device == -1)
222 jtag_add_plain_ir_scan(1, &field, TAP_PI);
223 else
224 jtag_add_ir_scan(1, &field, TAP_PI);
225 if (jtag_execute_queue() != ERROR_OK)
226 {
227 tdo_mismatch = 1;
228 free(ir_buf);
229 break;
230 }
231 if (xruntest)
232 {
233 if (runtest_requires_tck)
234 jtag_add_runtest(xruntest, xsvf_to_tap[xendir]);
235 else
236 {
237 xsvf_add_statemove(TAP_RTI);
238 jtag_add_sleep(xruntest);
239 xsvf_add_statemove(xsvf_to_tap[xendir]);
240 }
241 }
242 else if (xendir != 0xd) /* Pause-IR */
243 xsvf_add_statemove(xsvf_to_tap[xendir]);
244 }
245 free(ir_buf);
246 }
247 break;
248 case 0x03: /* XSDR */
249 LOG_DEBUG("XSDR");
250 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
251 do_abort = 1;
252 else
253 {
254 scan_field_t field;
255 field.device = device;
256 field.num_bits = xsdrsize;
257 field.out_value = dr_out_buf;
258 field.out_mask = NULL;
259 field.in_value = NULL;
260 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
261 if (device == -1)
262 jtag_add_plain_dr_scan(1, &field, TAP_PD);
263 else
264 jtag_add_dr_scan(1, &field, TAP_PD);
265 if (jtag_execute_queue() != ERROR_OK)
266 {
267 tdo_mismatch = 1;
268 break;
269 }
270 if (xruntest)
271 {
272 if (runtest_requires_tck)
273 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
274 else
275 {
276 xsvf_add_statemove(TAP_RTI);
277 jtag_add_sleep(xruntest);
278 xsvf_add_statemove(xsvf_to_tap[xenddr]);
279 }
280 }
281 else if (xendir != 0x6) /* Pause-DR */
282 xsvf_add_statemove(xsvf_to_tap[xenddr]);
283 }
284 break;
285 case 0x04: /* XRUNTEST */
286 LOG_DEBUG("XRUNTEST");
287 if (read(xsvf_fd, buf4, 4) < 0)
288 do_abort = 1;
289 else
290 {
291 xruntest = be_to_h_u32(buf4);
292 }
293 break;
294 case 0x07: /* XREPEAT */
295 LOG_DEBUG("XREPEAT");
296 if (read(xsvf_fd, &c, 1) < 0)
297 do_abort = 1;
298 else
299 {
300 xrepeat = c;
301 }
302 break;
303 case 0x08: /* XSDRSIZE */
304 LOG_DEBUG("XSDRSIZE");
305 if (read(xsvf_fd, buf4, 4) < 0)
306 do_abort = 1;
307 else
308 {
309 xsdrsize = be_to_h_u32(buf4);
310 free(dr_out_buf);
311 free(dr_in_buf);
312 free(dr_in_mask);
313 dr_out_buf = malloc((xsdrsize + 7) / 8);
314 dr_in_buf = malloc((xsdrsize + 7) / 8);
315 dr_in_mask = malloc((xsdrsize + 7) / 8);
316 }
317 break;
318 case 0x09: /* XSDRTDO */
319 LOG_DEBUG("XSDRTDO");
320 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
321 do_abort = 1;
322 else
323 {
324 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)
325 do_abort = 1;
326 else
327 {
328 scan_field_t field;
329 field.device = device;
330 field.num_bits = xsdrsize;
331 field.out_value = dr_out_buf;
332 field.out_mask = NULL;
333 field.in_value = NULL;
334 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
335 if (device == -1)
336 jtag_add_plain_dr_scan(1, &field, TAP_PD);
337 else
338 jtag_add_dr_scan(1, &field, TAP_PD);
339 if (jtag_execute_queue() != ERROR_OK)
340 {
341 tdo_mismatch = 1;
342 break;
343 }
344 if (xruntest)
345 {
346 if (runtest_requires_tck)
347 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
348 else
349 {
350 xsvf_add_statemove(TAP_RTI);
351 jtag_add_sleep(xruntest);
352 xsvf_add_statemove(xsvf_to_tap[xenddr]);
353 }
354 }
355 else if (xendir != 0x6) /* Pause-DR */
356 xsvf_add_statemove(xsvf_to_tap[xenddr]);
357 }
358 }
359 break;
360 case 0x0a: /* XSETDRMASKS */
361 LOG_ERROR("unsupported XSETSDRMASKS\n");
362 unsupported = 1;
363 break;
364 case 0x0b: /* XSDRINC */
365 LOG_ERROR("unsupported XSDRINC\n");
366 unsupported = 1;
367 break;
368 case 0x0c: /* XSDRB */
369 unsupported = 1;
370 break;
371 case 0x0d: /* XSDRC */
372 unsupported = 1;
373 break;
374 case 0x0e: /* XSDRE */
375 unsupported = 1;
376 break;
377 case 0x0f: /* XSDRTDOB */
378 unsupported = 1;
379 break;
380 case 0x10: /* XSDRTDOB */
381 unsupported = 1;
382 break;
383 case 0x11: /* XSDRTDOB */
384 unsupported = 1;
385 break;
386 case 0x12: /* XSTATE */
387 LOG_DEBUG("XSTATE");
388 if (read(xsvf_fd, &uc, 1) < 0)
389 do_abort = 1;
390 else
391 {
392 enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);
393 int path_len = 1;
394 path[0] = xsvf_to_tap[uc];
395 if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)
396 do_abort = 1;
397 else
398 {
399 jtag_add_pathmove(path_len, path);
400 }
401 free(path);
402 }
403 break;
404 case 0x13: /* XENDIR */
405 LOG_DEBUG("XENDIR");
406 if (read(xsvf_fd, &c, 1) < 0)
407 do_abort = 1;
408 else
409 {
410 if (c == 0)
411 xendir = 1;
412 else if (c == 1)
413 xendir = 0xd;
414 else
415 {
416 LOG_ERROR("unknown XENDIR endstate");
417 unsupported = 1;
418 }
419 }
420 break;
421 case 0x14: /* XENDDR */
422 LOG_DEBUG("XENDDR");
423 if (read(xsvf_fd, &c, 1) < 0)
424 do_abort = 1;
425 else
426 {
427 if (c == 0)
428 xenddr = 1;
429 else if (c == 1)
430 xenddr = 0x6;
431 else
432 {
433 LOG_ERROR("unknown XENDDR endstate");
434 unsupported = 1;
435 }
436 }
437 break;
438 case 0x15: /* XSIR2 */
439 LOG_DEBUG("XSIR2");
440 if (read(xsvf_fd, buf2, 2) < 0)
441 do_abort = 1;
442 else
443 {
444 u8 *ir_buf;
445 us = be_to_h_u16(buf2);
446 ir_buf = malloc((us + 7) / 8);
447 if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)
448 do_abort = 1;
449 else
450 {
451 scan_field_t field;
452 field.device = device;
453 field.num_bits = us;
454 field.out_value = ir_buf;
455 field.out_mask = NULL;
456 field.in_value = NULL;
457 field.in_check_value = NULL;
458 field.in_check_mask = NULL;
459 field.in_handler = NULL;
460 field.in_handler_priv = NULL;
461 if (device == -1)
462 jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);
463 else
464 jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);
465 }
466 free(ir_buf);
467 }
468 break;
469 case 0x16: /* XCOMMENT */
470 do
471 {
472 if (read(xsvf_fd, &c, 1) < 0)
473 {
474 do_abort = 1;
475 break;
476 }
477 } while (c != 0);
478 break;
479 case 0x17: /* XWAIT */
480 LOG_DEBUG("XWAIT");
481 if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))
482 do_abort = 1;
483 else
484 {
485 xsvf_add_statemove(xsvf_to_tap[uc]);
486 ui = be_to_h_u32(buf4);
487 jtag_add_sleep(ui);
488 xsvf_add_statemove(xsvf_to_tap[uc2]);
489 }
490 break;
491 default:
492 LOG_ERROR("unknown xsvf command (0x%2.2x)\n", c);
493 unsupported = 1;
494 }
495
496 if (do_abort || unsupported || tdo_mismatch)
497 break;
498 }
499
500 if (tdo_mismatch)
501 {
502 command_print(cmd_ctx, "TDO mismatch, aborting");
503 return ERROR_OK;
504 }
505
506 if (unsupported)
507 {
508 command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");
509 return ERROR_OK;
510 }
511
512 if (do_abort)
513 {
514 command_print(cmd_ctx, "premature end detected, aborting");
515 return ERROR_OK;
516 }
517
518 if (dr_out_buf)
519 free(dr_out_buf);
520
521 if (dr_in_buf)
522 free(dr_in_buf);
523
524 if (dr_in_mask)
525 free(dr_in_mask);
526
527 close(xsvf_fd);
528
529 command_print(cmd_ctx, "XSVF file programmed successfully");
530
531 return ERROR_OK;
532 }

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)