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

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)