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

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)