f4a6f6cdcc8b3c7c2298d68e1a55e9bff8e0f582
[openocd.git] / src / server / ipdbg.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (C) 2020 by Daniel Anselmi <danselmi@gmx.ch> */
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7
8 #include <helper/bits.h>
9 #include <helper/time_support.h>
10 #include <jtag/jtag.h>
11 #include <server/server.h>
12 #include <target/target.h>
13
14 #include "ipdbg.h"
15
16 #define IPDBG_BUFFER_SIZE 16384
17 #define IPDBG_MIN_NUM_OF_OPTIONS 4
18 #define IPDBG_MAX_NUM_OF_OPTIONS 14
19 #define IPDBG_MIN_DR_LENGTH 11
20 #define IPDBG_MAX_DR_LENGTH 13
21 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6
22
23 /* private connection data for IPDBG */
24 struct ipdbg_fifo {
25 size_t count;
26 size_t rd_idx;
27 char buffer[IPDBG_BUFFER_SIZE];
28 };
29
30 struct ipdbg_connection {
31 struct ipdbg_fifo dn_fifo;
32 struct ipdbg_fifo up_fifo;
33 bool closed;
34 };
35
36 struct ipdbg_service {
37 struct ipdbg_hub *hub;
38 struct ipdbg_service *next;
39 uint16_t port;
40 struct ipdbg_connection connection;
41 uint8_t tool;
42 };
43
44 struct ipdbg_virtual_ir_info {
45 uint32_t instruction;
46 uint32_t length;
47 uint32_t value;
48 };
49
50 struct ipdbg_hub {
51 uint32_t user_instruction;
52 uint32_t max_tools;
53 uint32_t active_connections;
54 uint32_t active_services;
55 uint32_t valid_mask;
56 uint32_t xoff_mask;
57 uint32_t tool_mask;
58 uint32_t last_dn_tool;
59 struct ipdbg_hub *next;
60 struct jtag_tap *tap;
61 struct connection **connections;
62 uint8_t data_register_length;
63 uint8_t dn_xoff;
64 struct ipdbg_virtual_ir_info *virtual_ir;
65 };
66
67 static struct ipdbg_hub *ipdbg_first_hub;
68
69 static struct ipdbg_service *ipdbg_first_service;
70
71 static void ipdbg_init_fifo(struct ipdbg_fifo *fifo)
72 {
73 fifo->count = 0;
74 fifo->rd_idx = 0;
75 }
76
77 static bool ipdbg_fifo_is_empty(struct ipdbg_fifo *fifo)
78 {
79 return fifo->count == 0;
80 }
81
82 static bool ipdbg_fifo_is_full(struct ipdbg_fifo *fifo)
83 {
84 return fifo->count == IPDBG_BUFFER_SIZE;
85 }
86
87 static void ipdbg_zero_rd_idx(struct ipdbg_fifo *fifo)
88 {
89 if (fifo->rd_idx == 0)
90 return;
91
92 size_t ri = fifo->rd_idx;
93 for (size_t idx = 0 ; idx < fifo->count ; ++idx)
94 fifo->buffer[idx] = fifo->buffer[ri++];
95 fifo->rd_idx = 0;
96 }
97
98 static void ipdbg_append_to_fifo(struct ipdbg_fifo *fifo, char data)
99 {
100 if (ipdbg_fifo_is_full(fifo))
101 return;
102
103 ipdbg_zero_rd_idx(fifo);
104 fifo->buffer[fifo->count++] = data;
105 }
106
107 static char ipdbg_get_from_fifo(struct ipdbg_fifo *fifo)
108 {
109 if (ipdbg_fifo_is_empty(fifo))
110 return 0;
111
112 fifo->count--;
113 return fifo->buffer[fifo->rd_idx++];
114 }
115
116 static int ipdbg_move_buffer_to_connection(struct connection *conn, struct ipdbg_fifo *fifo)
117 {
118 if (ipdbg_fifo_is_empty(fifo))
119 return ERROR_OK;
120
121 struct ipdbg_connection *connection = conn->priv;
122 if (connection->closed)
123 return ERROR_SERVER_REMOTE_CLOSED;
124
125 ipdbg_zero_rd_idx(fifo);
126 size_t bytes_written = connection_write(conn, fifo->buffer, fifo->count);
127 if (bytes_written != fifo->count) {
128 LOG_ERROR("error during write: %zu != %zu", bytes_written, fifo->count);
129 connection->closed = true;
130 return ERROR_SERVER_REMOTE_CLOSED;
131 }
132
133 fifo->count -= bytes_written;
134
135 return ERROR_OK;
136 }
137
138 static int ipdbg_max_tools_from_data_register_length(uint8_t data_register_length)
139 {
140 int max_tools = 1;
141 data_register_length -= 10; /* 8 bit payload, 1 xoff-flag, 1 valid-flag; remaining bits used to select tool*/
142 while (data_register_length--)
143 max_tools *= 2;
144
145 /* last tool is used to reset JtagCDC and transfer "XON" to host*/
146 return max_tools - 1;
147 }
148
149 static struct ipdbg_service *ipdbg_find_service(struct ipdbg_hub *hub, uint8_t tool)
150 {
151 struct ipdbg_service *service;
152 for (service = ipdbg_first_service ; service ; service = service->next) {
153 if (service->hub == hub && service->tool == tool)
154 break;
155 }
156 return service;
157 }
158
159 static void ipdbg_add_service(struct ipdbg_service *service)
160 {
161 struct ipdbg_service *iservice;
162 if (ipdbg_first_service) {
163 for (iservice = ipdbg_first_service ; iservice->next; iservice = iservice->next)
164 ;
165 iservice->next = service;
166 } else
167 ipdbg_first_service = service;
168 }
169
170 static int ipdbg_create_service(struct ipdbg_hub *hub, uint8_t tool, struct ipdbg_service **service, uint16_t port)
171 {
172 *service = calloc(1, sizeof(struct ipdbg_service));
173 if (!*service) {
174 LOG_ERROR("Out of memory");
175 return ERROR_FAIL;
176 }
177
178 (*service)->hub = hub;
179 (*service)->tool = tool;
180 (*service)->port = port;
181
182 return ERROR_OK;
183 }
184
185 static int ipdbg_remove_service(struct ipdbg_service *service)
186 {
187 if (!ipdbg_first_service)
188 return ERROR_FAIL;
189
190 if (service == ipdbg_first_service) {
191 ipdbg_first_service = ipdbg_first_service->next;
192 return ERROR_OK;
193 }
194
195 for (struct ipdbg_service *iservice = ipdbg_first_service ; iservice->next ; iservice = iservice->next) {
196 if (service == iservice->next) {
197 iservice->next = service->next;
198 return ERROR_OK;
199 }
200 }
201 return ERROR_FAIL;
202 }
203
204 static struct ipdbg_hub *ipdbg_find_hub(struct jtag_tap *tap,
205 uint32_t user_instruction, struct ipdbg_virtual_ir_info *virtual_ir)
206 {
207 struct ipdbg_hub *hub = NULL;
208 for (hub = ipdbg_first_hub ; hub ; hub = hub->next) {
209 if (hub->tap == tap && hub->user_instruction == user_instruction) {
210 if ((!virtual_ir && !hub->virtual_ir) ||
211 (virtual_ir && hub->virtual_ir &&
212 virtual_ir->instruction == hub->virtual_ir->instruction &&
213 virtual_ir->length == hub->virtual_ir->length &&
214 virtual_ir->value == hub->virtual_ir->value)) {
215 break;
216 }
217 }
218 }
219 return hub;
220 }
221
222 static void ipdbg_add_hub(struct ipdbg_hub *hub)
223 {
224 struct ipdbg_hub *ihub;
225 if (ipdbg_first_hub) {
226 for (ihub = ipdbg_first_hub ; ihub->next; ihub = ihub->next)
227 ;
228 ihub->next = hub;
229 } else
230 ipdbg_first_hub = hub;
231 }
232
233 static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length,
234 struct ipdbg_virtual_ir_info *virtual_ir, struct ipdbg_hub **hub)
235 {
236 *hub = NULL;
237 struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
238 if (!new_hub) {
239 free(virtual_ir);
240 LOG_ERROR("Out of memory");
241 return ERROR_FAIL;
242 }
243
244 new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
245 new_hub->connections = calloc(new_hub->max_tools, sizeof(struct connection *));
246 if (!new_hub->connections) {
247 free(virtual_ir);
248 free(new_hub);
249 LOG_ERROR("Out of memory");
250 return ERROR_FAIL;
251 }
252 new_hub->tap = tap;
253 new_hub->user_instruction = user_instruction;
254 new_hub->data_register_length = data_register_length;
255 new_hub->valid_mask = BIT(data_register_length - 1);
256 new_hub->xoff_mask = BIT(data_register_length - 2);
257 new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
258 new_hub->last_dn_tool = new_hub->tool_mask;
259 new_hub->virtual_ir = virtual_ir;
260
261 *hub = new_hub;
262
263 return ERROR_OK;
264 }
265
266 static void ipdbg_free_hub(struct ipdbg_hub *hub)
267 {
268 if (!hub)
269 return;
270 free(hub->connections);
271 free(hub->virtual_ir);
272 free(hub);
273 }
274
275 static int ipdbg_remove_hub(struct ipdbg_hub *hub)
276 {
277 if (!ipdbg_first_hub)
278 return ERROR_FAIL;
279 if (hub == ipdbg_first_hub) {
280 ipdbg_first_hub = ipdbg_first_hub->next;
281 return ERROR_OK;
282 }
283
284 for (struct ipdbg_hub *ihub = ipdbg_first_hub ; ihub->next ; ihub = ihub->next) {
285 if (hub == ihub->next) {
286 ihub->next = hub->next;
287 return ERROR_OK;
288 }
289 }
290
291 return ERROR_FAIL;
292 }
293
294 static void ipdbg_init_scan_field(struct scan_field *fields, uint8_t *in_value, int num_bits, const uint8_t *out_value)
295 {
296 fields->check_mask = NULL;
297 fields->check_value = NULL;
298 fields->in_value = in_value;
299 fields->num_bits = num_bits;
300 fields->out_value = out_value;
301 }
302
303 static int ipdbg_shift_instr(struct ipdbg_hub *hub, uint32_t instr)
304 {
305 if (!hub)
306 return ERROR_FAIL;
307
308 struct jtag_tap *tap = hub->tap;
309 if (!tap)
310 return ERROR_FAIL;
311
312 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == instr) {
313 /* there is already the requested instruction in the ir */
314 return ERROR_OK;
315 }
316
317 uint8_t *ir_out_val = calloc(DIV_ROUND_UP(tap->ir_length, 8), 1);
318 buf_set_u32(ir_out_val, 0, tap->ir_length, instr);
319
320 struct scan_field fields;
321 ipdbg_init_scan_field(&fields, NULL, tap->ir_length, ir_out_val);
322 jtag_add_ir_scan(tap, &fields, TAP_IDLE);
323 int retval = jtag_execute_queue();
324
325 free(ir_out_val);
326
327 return retval;
328 }
329
330 static int ipdbg_shift_vir(struct ipdbg_hub *hub)
331 {
332 if (!hub)
333 return ERROR_FAIL;
334
335 if (!hub->virtual_ir)
336 return ERROR_OK;
337
338 int retval = ipdbg_shift_instr(hub, hub->virtual_ir->instruction);
339 if (retval != ERROR_OK)
340 return retval;
341
342 struct jtag_tap *tap = hub->tap;
343 if (!tap)
344 return ERROR_FAIL;
345
346 uint8_t *dr_out_val = calloc(DIV_ROUND_UP(hub->virtual_ir->length, 8), 1);
347 buf_set_u32(dr_out_val, 0, hub->virtual_ir->length, hub->virtual_ir->value);
348
349 struct scan_field fields;
350 ipdbg_init_scan_field(&fields, NULL, hub->virtual_ir->length, dr_out_val);
351 jtag_add_dr_scan(tap, 1, &fields, TAP_IDLE);
352 retval = jtag_execute_queue();
353
354 free(dr_out_val);
355
356 return retval;
357 }
358
359 static int ipdbg_shift_data(struct ipdbg_hub *hub, uint32_t dn_data, uint32_t *up_data)
360 {
361 if (!hub)
362 return ERROR_FAIL;
363
364 struct jtag_tap *tap = hub->tap;
365 if (!tap)
366 return ERROR_FAIL;
367
368 uint8_t *dr_out_val = calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1);
369 buf_set_u32(dr_out_val, 0, hub->data_register_length, dn_data);
370 uint8_t *dr_in_val = up_data ? calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1) : NULL;
371
372 struct scan_field fields;
373 ipdbg_init_scan_field(&fields, dr_in_val, hub->data_register_length, dr_out_val);
374 jtag_add_dr_scan(tap, 1, &fields, TAP_IDLE);
375 int retval = jtag_execute_queue();
376
377 if (up_data && retval == ERROR_OK)
378 *up_data = buf_get_u32(dr_in_val, 0, hub->data_register_length);
379
380 free(dr_out_val);
381 free(dr_in_val);
382
383 return retval;
384 }
385
386 static int ipdbg_distribute_data_from_hub(struct ipdbg_hub *hub, uint32_t up)
387 {
388 const bool valid_up_data = up & hub->valid_mask;
389 if (!valid_up_data)
390 return ERROR_OK;
391
392 const size_t tool = (up >> 8) & hub->tool_mask;
393 if (tool == hub->tool_mask) {
394 const uint8_t xon_cmd = up & 0x00ff;
395 hub->dn_xoff &= ~xon_cmd;
396 LOG_INFO("received xon cmd: %d\n", xon_cmd);
397 return ERROR_OK;
398 }
399
400 struct connection *conn = hub->connections[tool];
401 if (conn) {
402 struct ipdbg_connection *connection = conn->priv;
403 if (ipdbg_fifo_is_full(&connection->up_fifo)) {
404 int retval = ipdbg_move_buffer_to_connection(conn, &connection->up_fifo);
405 if (retval != ERROR_OK)
406 return retval;
407 }
408 ipdbg_append_to_fifo(&connection->up_fifo, up);
409 }
410 return ERROR_OK;
411 }
412
413 static int ipdbg_jtag_transfer_byte(struct ipdbg_hub *hub, size_t tool, struct ipdbg_connection *connection)
414 {
415 uint32_t dn = hub->valid_mask | ((tool & hub->tool_mask) << 8) |
416 (0x00fful & ipdbg_get_from_fifo(&connection->dn_fifo));
417 uint32_t up = 0;
418 int ret = ipdbg_shift_data(hub, dn, &up);
419 if (ret != ERROR_OK)
420 return ret;
421
422 ret = ipdbg_distribute_data_from_hub(hub, up);
423 if (ret != ERROR_OK)
424 return ret;
425
426 if ((up & hub->xoff_mask) && (hub->last_dn_tool != hub->max_tools)) {
427 hub->dn_xoff |= BIT(hub->last_dn_tool);
428 LOG_INFO("tool %d sent xoff", hub->last_dn_tool);
429 }
430
431 hub->last_dn_tool = tool;
432
433 return ERROR_OK;
434 }
435
436 static int ipdbg_polling_callback(void *priv)
437 {
438 struct ipdbg_hub *hub = priv;
439
440 int ret = ipdbg_shift_vir(hub);
441 if (ret != ERROR_OK)
442 return ret;
443
444 ret = ipdbg_shift_instr(hub, hub->user_instruction);
445 if (ret != ERROR_OK)
446 return ret;
447
448 /* transfer dn buffers to jtag-hub */
449 unsigned int num_transfers = 0;
450 for (size_t tool = 0 ; tool < hub->max_tools ; ++tool) {
451 struct connection *conn = hub->connections[tool];
452 if (conn && conn->priv) {
453 struct ipdbg_connection *connection = conn->priv;
454 while (((hub->dn_xoff & BIT(tool)) == 0) && !ipdbg_fifo_is_empty(&connection->dn_fifo)) {
455 ret = ipdbg_jtag_transfer_byte(hub, tool, connection);
456 if (ret != ERROR_OK)
457 return ret;
458 ++num_transfers;
459 }
460 }
461 }
462
463 /* some transfers to get data from jtag-hub in case there is no dn data */
464 while (num_transfers++ < hub->max_tools) {
465 uint32_t dn = 0;
466 uint32_t up = 0;
467
468 int retval = ipdbg_shift_data(hub, dn, &up);
469 if (retval != ERROR_OK)
470 return ret;
471
472 retval = ipdbg_distribute_data_from_hub(hub, up);
473 if (retval != ERROR_OK)
474 return ret;
475 }
476
477 /* write from up fifos to sockets */
478 for (size_t tool = 0 ; tool < hub->max_tools ; ++tool) {
479 struct connection *conn = hub->connections[tool];
480 if (conn && conn->priv) {
481 struct ipdbg_connection *connection = conn->priv;
482 int retval = ipdbg_move_buffer_to_connection(conn, &connection->up_fifo);
483 if (retval != ERROR_OK)
484 return retval;
485 }
486 }
487
488 return ERROR_OK;
489 }
490
491 static int ipdbg_start_polling(struct ipdbg_service *service, struct connection *connection)
492 {
493 struct ipdbg_hub *hub = service->hub;
494 hub->connections[service->tool] = connection;
495 hub->active_connections++;
496 if (hub->active_connections > 1) {
497 /* hub is already initialized */
498 return ERROR_OK;
499 }
500
501 const uint32_t reset_hub = hub->valid_mask | ((hub->max_tools) << 8);
502
503 int ret = ipdbg_shift_vir(hub);
504 if (ret != ERROR_OK)
505 return ret;
506
507 ret = ipdbg_shift_instr(hub, hub->user_instruction);
508 if (ret != ERROR_OK)
509 return ret;
510
511 ret = ipdbg_shift_data(hub, reset_hub, NULL);
512 hub->last_dn_tool = hub->tool_mask;
513 hub->dn_xoff = 0;
514 if (ret != ERROR_OK)
515 return ret;
516
517 LOG_INFO("IPDBG start_polling");
518
519 const int time_ms = 20;
520 const int periodic = 1;
521 return target_register_timer_callback(ipdbg_polling_callback, time_ms, periodic, hub);
522 }
523
524 static int ipdbg_stop_polling(struct ipdbg_service *service)
525 {
526 struct ipdbg_hub *hub = service->hub;
527 hub->connections[service->tool] = NULL;
528 hub->active_connections--;
529 if (hub->active_connections == 0) {
530 LOG_INFO("IPDBG stop_polling");
531
532 return target_unregister_timer_callback(ipdbg_polling_callback, hub);
533 }
534
535 return ERROR_OK;
536 }
537
538 static int ipdbg_on_new_connection(struct connection *connection)
539 {
540 struct ipdbg_service *service = connection->service->priv;
541 connection->priv = &service->connection;
542 /* initialize ipdbg connection information */
543 ipdbg_init_fifo(&service->connection.up_fifo);
544 ipdbg_init_fifo(&service->connection.dn_fifo);
545
546 int retval = ipdbg_start_polling(service, connection);
547 if (retval != ERROR_OK) {
548 LOG_ERROR("BUG: ipdbg_start_polling failed");
549 return retval;
550 }
551
552 struct ipdbg_connection *conn = connection->priv;
553 conn->closed = false;
554
555 LOG_INFO("New IPDBG Connection");
556
557 return ERROR_OK;
558 }
559
560 static int ipdbg_on_connection_input(struct connection *connection)
561 {
562 struct ipdbg_connection *conn = connection->priv;
563 struct ipdbg_fifo *fifo = &conn->dn_fifo;
564
565 if (ipdbg_fifo_is_full(fifo))
566 return ERROR_OK;
567
568 ipdbg_zero_rd_idx(fifo);
569 int bytes_read = connection_read(connection, fifo->buffer + fifo->count, IPDBG_BUFFER_SIZE - fifo->count);
570 if (bytes_read <= 0) {
571 if (bytes_read < 0)
572 LOG_ERROR("error during read: %s", strerror(errno));
573 return ERROR_SERVER_REMOTE_CLOSED;
574 }
575
576 fifo->count += bytes_read;
577
578 return ERROR_OK;
579 }
580
581 static int ipdbg_on_connection_closed(struct connection *connection)
582 {
583 struct ipdbg_connection *conn = connection->priv;
584 conn->closed = true;
585 LOG_INFO("Closed IPDBG Connection");
586
587 return ipdbg_stop_polling(connection->service->priv);
588 }
589
590 static const struct service_driver ipdbg_service_driver = {
591 .name = "ipdbg",
592 .new_connection_during_keep_alive_handler = NULL,
593 .new_connection_handler = ipdbg_on_new_connection,
594 .input_handler = ipdbg_on_connection_input,
595 .connection_closed_handler = ipdbg_on_connection_closed,
596 .keep_client_alive_handler = NULL,
597 };
598
599 static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instruction,
600 uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
601 {
602 LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool);
603
604 struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
605 if (hub) {
606 free(virtual_ir);
607 if (hub->data_register_length != data_register_length) {
608 LOG_DEBUG("hub must have the same data_register_length for all tools");
609 return ERROR_FAIL;
610 }
611 } else {
612 int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub);
613 if (retval != ERROR_OK) {
614 free(virtual_ir);
615 return retval;
616 }
617 }
618
619 struct ipdbg_service *service = NULL;
620 int retval = ipdbg_create_service(hub, tool, &service, port);
621
622 if (retval != ERROR_OK || !service) {
623 if (hub->active_services == 0 && hub->active_connections == 0)
624 ipdbg_free_hub(hub);
625 return ERROR_FAIL;
626 }
627
628 char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
629 snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port);
630 retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service);
631 if (retval == ERROR_OK) {
632 ipdbg_add_service(service);
633 if (hub->active_services == 0 && hub->active_connections == 0)
634 ipdbg_add_hub(hub);
635 hub->active_services++;
636 } else {
637 if (hub->active_services == 0 && hub->active_connections == 0)
638 ipdbg_free_hub(hub);
639 free(service);
640 }
641
642 return retval;
643 }
644
645 static int ipdbg_stop(struct jtag_tap *tap, uint32_t user_instruction,
646 struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
647 {
648 struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
649 free(virtual_ir);
650 if (!hub)
651 return ERROR_FAIL;
652
653 struct ipdbg_service *service = ipdbg_find_service(hub, tool);
654 if (!service)
655 return ERROR_FAIL;
656
657 int retval = ipdbg_remove_service(service);
658 if (retval != ERROR_OK) {
659 LOG_ERROR("BUG: ipdbg_remove_service failed");
660 return retval;
661 }
662
663 char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
664 snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", service->port);
665 retval = remove_service("ipdbg", port_str_buffer);
666 /* The ipdbg_service structure is freed by server.c:remove_service().
667 There the "priv" pointer is freed.*/
668 if (retval != ERROR_OK) {
669 LOG_ERROR("BUG: remove_service failed");
670 return retval;
671 }
672 hub->active_services--;
673 if (hub->active_connections == 0 && hub->active_services == 0) {
674 retval = ipdbg_remove_hub(hub);
675 if (retval != ERROR_OK) {
676 LOG_ERROR("BUG: ipdbg_remove_hub failed");
677 return retval;
678 }
679 ipdbg_free_hub(hub);
680 }
681 return ERROR_OK;
682 }
683
684 COMMAND_HANDLER(handle_ipdbg_command)
685 {
686 struct jtag_tap *tap = NULL;
687 uint16_t port = 4242;
688 uint8_t tool = 1;
689 uint32_t user_instruction = 0x00;
690 uint8_t data_register_length = IPDBG_MAX_DR_LENGTH;
691 bool start = true;
692 bool hub_configured = false;
693 bool has_virtual_ir = false;
694 uint32_t virtual_ir_instruction = 0x00e;
695 uint32_t virtual_ir_length = 5;
696 uint32_t virtual_ir_value = 0x11;
697 struct ipdbg_virtual_ir_info *virtual_ir = NULL;
698
699 if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
700 return ERROR_COMMAND_SYNTAX_ERROR;
701
702 for (unsigned int i = 0; i < CMD_ARGC; ++i) {
703 if (strcmp(CMD_ARGV[i], "-tap") == 0) {
704 if (i + 1 >= CMD_ARGC || CMD_ARGV[i + 1][0] == '-') {
705 command_print(CMD, "no TAP given");
706 return ERROR_FAIL;
707 }
708 tap = jtag_tap_by_string(CMD_ARGV[i + 1]);
709 if (!tap) {
710 command_print(CMD, "Tap %s unknown", CMD_ARGV[i + 1]);
711 return ERROR_FAIL;
712 }
713 ++i;
714 } else if (strcmp(CMD_ARGV[i], "-hub") == 0) {
715 COMMAND_PARSE_ADDITIONAL_NUMBER(u32, i, user_instruction, "ir_value to select hub");
716 hub_configured = true;
717 COMMAND_PARSE_OPTIONAL_NUMBER(u8, i, data_register_length);
718 if (data_register_length < IPDBG_MIN_DR_LENGTH ||
719 data_register_length > IPDBG_MAX_DR_LENGTH) {
720 command_print(CMD, "length of \"user\"-data register must be at least %d and at most %d.",
721 IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH);
722 return ERROR_FAIL;
723 }
724 } else if (strcmp(CMD_ARGV[i], "-vir") == 0) {
725 COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value);
726 COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
727 COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_instruction);
728 has_virtual_ir = true;
729 } else if (strcmp(CMD_ARGV[i], "-port") == 0) {
730 COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number");
731 } else if (strcmp(CMD_ARGV[i], "-tool") == 0) {
732 COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
733 } else if (strcmp(CMD_ARGV[i], "-stop") == 0) {
734 start = false;
735 } else if (strcmp(CMD_ARGV[i], "-start") == 0) {
736 start = true;
737 } else {
738 command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
739 return ERROR_FAIL;
740 }
741 }
742
743 if (!tap) {
744 command_print(CMD, "no valid tap selected");
745 return ERROR_FAIL;
746 }
747
748 if (!hub_configured) {
749 command_print(CMD, "hub not configured correctly");
750 return ERROR_FAIL;
751 }
752
753 if (tool >= ipdbg_max_tools_from_data_register_length(data_register_length)) {
754 command_print(CMD, "Tool: %d is invalid", tool);
755 return ERROR_FAIL;
756 }
757
758 if (has_virtual_ir) {
759 virtual_ir = calloc(1, sizeof(struct ipdbg_virtual_ir_info));
760 if (!virtual_ir) {
761 LOG_ERROR("Out of memory");
762 return ERROR_FAIL;
763 }
764 virtual_ir->instruction = virtual_ir_instruction;
765 virtual_ir->length = virtual_ir_length;
766 virtual_ir->value = virtual_ir_value;
767 }
768
769 if (start)
770 return ipdbg_start(port, tap, user_instruction, data_register_length, virtual_ir, tool);
771 else
772 return ipdbg_stop(tap, user_instruction, virtual_ir, tool);
773 }
774
775 static const struct command_registration ipdbg_command_handlers[] = {
776 {
777 .name = "ipdbg",
778 .handler = handle_ipdbg_command,
779 .mode = COMMAND_EXEC,
780 .help = "Starts or stops an IPDBG JTAG-Host server.",
781 .usage = "[-start|-stop] -tap device.tap -hub ir_value [dr_length]"
782 " [-port number] [-tool number] [-vir [vir_value [length [instr_code]]]]",
783 },
784 COMMAND_REGISTRATION_DONE
785 };
786
787 int ipdbg_register_commands(struct command_context *cmd_ctx)
788 {
789 return register_commands(cmd_ctx, NULL, ipdbg_command_handlers);
790 }

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)