- rename log functions to stop conflicts under win32 (wingdi)
[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 LOG_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 LOG_DEBUG("XCOMPLETE");
158 if (jtag_execute_queue() != ERROR_OK)
159 {
160 tdo_mismatch = 1;
161 break;
162 }
163 break;
164 case 0x01: /* XTDOMASK */
165 LOG_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 LOG_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 LOG_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 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
230 if (device == -1)
231 jtag_add_plain_dr_scan(1, &field, TAP_PD);
232 else
233 jtag_add_dr_scan(1, &field, TAP_PD);
234 if (jtag_execute_queue() != ERROR_OK)
235 {
236 tdo_mismatch = 1;
237 break;
238 }
239 if (xruntest)
240 {
241 if (runtest_requires_tck)
242 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
243 else
244 {
245 jtag_add_statemove(TAP_RTI);
246 jtag_add_sleep(xruntest);
247 jtag_add_statemove(xsvf_to_tap[xenddr]);
248 }
249 }
250 else if (xendir != 0x6) /* Pause-DR */
251 jtag_add_statemove(xsvf_to_tap[xenddr]);
252 }
253 break;
254 case 0x04: /* XRUNTEST */
255 LOG_DEBUG("XRUNTEST");
256 if (read(xsvf_fd, buf4, 4) < 0)
257 do_abort = 1;
258 else
259 {
260 xruntest = be_to_h_u32(buf4);
261 }
262 break;
263 case 0x07: /* XREPEAT */
264 LOG_DEBUG("XREPEAT");
265 if (read(xsvf_fd, &c, 1) < 0)
266 do_abort = 1;
267 else
268 {
269 xrepeat = c;
270 }
271 break;
272 case 0x08: /* XSDRSIZE */
273 LOG_DEBUG("XSDRSIZE");
274 if (read(xsvf_fd, buf4, 4) < 0)
275 do_abort = 1;
276 else
277 {
278 xsdrsize = be_to_h_u32(buf4);
279 free(dr_out_buf);
280 free(dr_in_buf);
281 free(dr_in_mask);
282 dr_out_buf = malloc((xsdrsize + 7) / 8);
283 dr_in_buf = malloc((xsdrsize + 7) / 8);
284 dr_in_mask = malloc((xsdrsize + 7) / 8);
285 }
286 break;
287 case 0x09: /* XSDRTDO */
288 LOG_DEBUG("XSDRTDO");
289 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
290 do_abort = 1;
291 else
292 {
293 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)
294 do_abort = 1;
295 else
296 {
297 scan_field_t field;
298 field.device = device;
299 field.num_bits = xsdrsize;
300 field.out_value = dr_out_buf;
301 field.out_mask = NULL;
302 field.in_value = NULL;
303 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
304 if (device == -1)
305 jtag_add_plain_dr_scan(1, &field, TAP_PD);
306 else
307 jtag_add_dr_scan(1, &field, TAP_PD);
308 if (jtag_execute_queue() != ERROR_OK)
309 {
310 tdo_mismatch = 1;
311 break;
312 }
313 if (xruntest)
314 {
315 if (runtest_requires_tck)
316 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
317 else
318 {
319 jtag_add_statemove(TAP_RTI);
320 jtag_add_sleep(xruntest);
321 jtag_add_statemove(xsvf_to_tap[xenddr]);
322 }
323 }
324 else if (xendir != 0x6) /* Pause-DR */
325 jtag_add_statemove(xsvf_to_tap[xenddr]);
326 }
327 }
328 break;
329 case 0x0a: /* XSETDRMASKS */
330 LOG_ERROR("unsupported XSETSDRMASKS\n");
331 unsupported = 1;
332 break;
333 case 0x0b: /* XSDRINC */
334 LOG_ERROR("unsupported XSDRINC\n");
335 unsupported = 1;
336 break;
337 case 0x0c: /* XSDRB */
338 unsupported = 1;
339 break;
340 case 0x0d: /* XSDRC */
341 unsupported = 1;
342 break;
343 case 0x0e: /* XSDRE */
344 unsupported = 1;
345 break;
346 case 0x0f: /* XSDRTDOB */
347 unsupported = 1;
348 break;
349 case 0x10: /* XSDRTDOB */
350 unsupported = 1;
351 break;
352 case 0x11: /* XSDRTDOB */
353 unsupported = 1;
354 break;
355 case 0x12: /* XSTATE */
356 LOG_DEBUG("XSTATE");
357 if (read(xsvf_fd, &uc, 1) < 0)
358 do_abort = 1;
359 else
360 {
361 enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);
362 int path_len = 1;
363 path[0] = xsvf_to_tap[uc];
364 if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)
365 do_abort = 1;
366 else
367 {
368 jtag_add_pathmove(path_len, path);
369 }
370 free(path);
371 }
372 break;
373 case 0x13: /* XENDIR */
374 LOG_DEBUG("XENDIR");
375 if (read(xsvf_fd, &c, 1) < 0)
376 do_abort = 1;
377 else
378 {
379 if (c == 0)
380 xendir = 1;
381 else if (c == 1)
382 xendir = 0xd;
383 else
384 {
385 LOG_ERROR("unknown XENDIR endstate");
386 unsupported = 1;
387 }
388 }
389 break;
390 case 0x14: /* XENDDR */
391 LOG_DEBUG("XENDDR");
392 if (read(xsvf_fd, &c, 1) < 0)
393 do_abort = 1;
394 else
395 {
396 if (c == 0)
397 xenddr = 1;
398 else if (c == 1)
399 xenddr = 0x6;
400 else
401 {
402 LOG_ERROR("unknown XENDDR endstate");
403 unsupported = 1;
404 }
405 }
406 break;
407 case 0x15: /* XSIR2 */
408 LOG_DEBUG("XSIR2");
409 if (read(xsvf_fd, buf2, 2) < 0)
410 do_abort = 1;
411 else
412 {
413 u8 *ir_buf;
414 us = be_to_h_u16(buf2);
415 ir_buf = malloc((us + 7) / 8);
416 if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)
417 do_abort = 1;
418 else
419 {
420 scan_field_t field;
421 field.device = device;
422 field.num_bits = us;
423 field.out_value = ir_buf;
424 field.out_mask = NULL;
425 field.in_value = NULL;
426 field.in_check_value = NULL;
427 field.in_check_mask = NULL;
428 field.in_handler = NULL;
429 field.in_handler_priv = NULL;
430 if (device == -1)
431 jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);
432 else
433 jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);
434 }
435 free(ir_buf);
436 }
437 break;
438 case 0x16: /* XCOMMENT */
439 do
440 {
441 if (read(xsvf_fd, &c, 1) < 0)
442 {
443 do_abort = 1;
444 break;
445 }
446 } while (c != 0);
447 break;
448 case 0x17: /* XWAIT */
449 LOG_DEBUG("XWAIT");
450 if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))
451 do_abort = 1;
452 else
453 {
454 jtag_add_statemove(xsvf_to_tap[uc]);
455 ui = be_to_h_u32(buf4);
456 jtag_add_sleep(ui);
457 jtag_add_statemove(xsvf_to_tap[uc2]);
458 }
459 break;
460 default:
461 LOG_ERROR("unknown xsvf command (0x%2.2x)\n", c);
462 unsupported = 1;
463 }
464
465 if (do_abort || unsupported || tdo_mismatch)
466 break;
467 }
468
469 if (tdo_mismatch)
470 {
471 command_print(cmd_ctx, "TDO mismatch, aborting");
472 return ERROR_OK;
473 }
474
475 if (unsupported)
476 {
477 command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");
478 return ERROR_OK;
479 }
480
481 if (do_abort)
482 {
483 command_print(cmd_ctx, "premature end detected, aborting");
484 return ERROR_OK;
485 }
486
487 if (dr_out_buf)
488 free(dr_out_buf);
489
490 if (dr_in_buf)
491 free(dr_in_buf);
492
493 if (dr_in_mask)
494 free(dr_in_mask);
495
496 close(xsvf_fd);
497
498 command_print(cmd_ctx, "XSVF file programmed successfully");
499
500 return ERROR_OK;
501 }

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)