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

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)