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

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)