Charles Hardin ckhardin at gmail.com Instead of stashing the context in a global...
[openocd.git] / src / openocd.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
21 #define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "log.h"
28 #include "types.h"
29 #include "jtag.h"
30 #include "configuration.h"
31 #include "xsvf.h"
32 #include "target.h"
33 #include "flash.h"
34 #include "nand.h"
35 #include "pld.h"
36
37 #include "command.h"
38 #include "server.h"
39 #include "telnet_server.h"
40 #include "gdb_server.h"
41 #include "tcl_server.h"
42
43 #include <sys/time.h>
44 #include <sys/types.h>
45 #include <strings.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <errno.h>
51
52 #ifdef _WIN32
53 #include <malloc.h>
54 #else
55 #include <alloca.h>
56 #endif
57
58 #ifdef __ECOS
59 /* Jim is provied by eCos */
60 #include <cyg/jimtcl/jim.h>
61 #else
62 #define JIM_EMBEDDED
63 #include "jim.h"
64 #endif
65
66 #include "replacements.h"
67
68
69 /* Give TELNET a way to find out what version this is */
70 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
71 {
72 command_print(cmd_ctx, OPENOCD_VERSION);
73
74 return ERROR_OK;
75 }
76
77 static int daemon_startup = 0;
78
79 int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
80 {
81 if (argc==0)
82 return ERROR_OK;
83 if (argc > 1 )
84 return ERROR_COMMAND_SYNTAX_ERROR;
85
86 daemon_startup = strcmp("reset", args[0])==0;
87
88 command_print(cmd_ctx, OPENOCD_VERSION);
89
90 return ERROR_OK;
91 }
92
93 void exit_handler(void)
94 {
95 /* close JTAG interface */
96 if (jtag && jtag->quit)
97 jtag->quit();
98 }
99
100 /* OpenOCD can't really handle failure of this command. Patches welcome! :-) */
101 int handle_init_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
102 {
103 int retval;
104 static int initialized=0;
105 if (initialized)
106 return ERROR_OK;
107
108 initialized=1;
109
110 atexit(exit_handler);
111
112 if (target_init(cmd_ctx) != ERROR_OK)
113 return ERROR_FAIL;
114 LOG_DEBUG("target init complete");
115
116 if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
117 {
118 /* we must be able to set up the jtag interface */
119 return retval;
120 }
121 LOG_DEBUG("jtag interface init complete");
122
123 /* Try to initialize & examine the JTAG chain at this point, but
124 * continue startup regardless */
125 if (jtag_init(cmd_ctx) == ERROR_OK)
126 {
127 LOG_DEBUG("jtag init complete");
128 if (target_examine(cmd_ctx) == ERROR_OK)
129 {
130 LOG_DEBUG("jtag examine complete");
131 }
132 }
133
134 if (flash_init_drivers(cmd_ctx) != ERROR_OK)
135 return ERROR_FAIL;
136 LOG_DEBUG("flash init complete");
137
138 if (nand_init(cmd_ctx) != ERROR_OK)
139 return ERROR_FAIL;
140 LOG_DEBUG("NAND init complete");
141
142 if (pld_init(cmd_ctx) != ERROR_OK)
143 return ERROR_FAIL;
144 LOG_DEBUG("pld init complete");
145
146 /* initialize tcp server */
147 server_init();
148
149 /* initialize telnet subsystem */
150 telnet_init("Open On-Chip Debugger");
151 gdb_init();
152 tcl_init(); /* allows tcl to just connect without going thru telnet */
153
154 return ERROR_OK;
155 }
156
157 Jim_Interp *interp;
158
159 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
160 {
161 char *namebuf;
162 Jim_Obj *nameObjPtr, *valObjPtr;
163 int result;
164
165 namebuf = alloc_printf("%s(%d)", varname, idx);
166 if (!namebuf)
167 return JIM_ERR;
168
169 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
170 valObjPtr = Jim_NewIntObj(interp, val);
171 if (!nameObjPtr || !valObjPtr)
172 {
173 free(namebuf);
174 return JIM_ERR;
175 }
176
177 Jim_IncrRefCount(nameObjPtr);
178 Jim_IncrRefCount(valObjPtr);
179 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
180 Jim_DecrRefCount(interp, nameObjPtr);
181 Jim_DecrRefCount(interp, valObjPtr);
182 free(namebuf);
183 /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
184 return result;
185 }
186
187 static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
188 {
189 target_t *target;
190 command_context_t *context;
191 long l;
192 u32 width;
193 u32 len;
194 u32 addr;
195 u32 count;
196 u32 v;
197 const char *varname;
198 u8 buffer[4096];
199 int i, n, e, retval;
200
201 /* argv[1] = name of array to receive the data
202 * argv[2] = desired width
203 * argv[3] = memory address
204 * argv[4] = count of times to read
205 */
206 if (argc != 5) {
207 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
208 return JIM_ERR;
209 }
210 varname = Jim_GetString(argv[1], &len);
211 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
212
213 e = Jim_GetLong(interp, argv[2], &l);
214 width = l;
215 if (e != JIM_OK) {
216 return e;
217 }
218
219 e = Jim_GetLong(interp, argv[3], &l);
220 addr = l;
221 if (e != JIM_OK) {
222 return e;
223 }
224 e = Jim_GetLong(interp, argv[4], &l);
225 len = l;
226 if (e != JIM_OK) {
227 return e;
228 }
229 switch (width) {
230 case 8:
231 width = 1;
232 break;
233 case 16:
234 width = 2;
235 break;
236 case 32:
237 width = 4;
238 break;
239 default:
240 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
241 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
242 return JIM_ERR;
243 }
244 if (len == 0) {
245 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
246 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
247 return JIM_ERR;
248 }
249 if ((addr + (len * width)) < addr) {
250 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
251 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
252 return JIM_ERR;
253 }
254 /* absurd transfer size? */
255 if (len > 65536) {
256 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
257 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
258 return JIM_ERR;
259 }
260
261 if ((width == 1) ||
262 ((width == 2) && ((addr & 1) == 0)) ||
263 ((width == 4) && ((addr & 3) == 0))) {
264 /* all is well */
265 } else {
266 char buf[100];
267 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
268 sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
269 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
270 return JIM_ERR;
271 }
272
273 context = Jim_GetAssocData(interp, "context");
274 if (context == NULL)
275 {
276 LOG_ERROR("mem2array: no command context");
277 return JIM_ERR;
278 }
279 target = get_current_target(context);
280 if (target == NULL)
281 {
282 LOG_ERROR("mem2array: no current target");
283 return JIM_ERR;
284 }
285
286 /* Transfer loop */
287
288 /* index counter */
289 n = 0;
290 /* assume ok */
291 e = JIM_OK;
292 while (len) {
293 /* Slurp... in buffer size chunks */
294
295 count = len; /* in objects.. */
296 if (count > (sizeof(buffer)/width)) {
297 count = (sizeof(buffer)/width);
298 }
299
300 retval = target->type->read_memory( target, addr, width, count, buffer );
301 if (retval != ERROR_OK) {
302 /* BOO !*/
303 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
304 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
305 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
306 e = JIM_ERR;
307 len = 0;
308 } else {
309 v = 0; /* shut up gcc */
310 for (i = 0 ;i < count ;i++, n++) {
311 switch (width) {
312 case 4:
313 v = target_buffer_get_u32(target, &buffer[i*width]);
314 break;
315 case 2:
316 v = target_buffer_get_u16(target, &buffer[i*width]);
317 break;
318 case 1:
319 v = buffer[i] & 0x0ff;
320 break;
321 }
322 new_int_array_element(interp, varname, n, v);
323 }
324 len -= count;
325 }
326 }
327
328 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
329
330 return JIM_OK;
331 }
332
333 static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)
334 {
335 char *namebuf;
336 Jim_Obj *nameObjPtr, *valObjPtr;
337 int result;
338 long l;
339
340 namebuf = alloc_printf("%s(%d)", varname, idx);
341 if (!namebuf)
342 return JIM_ERR;
343
344 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
345 if (!nameObjPtr)
346 {
347 free(namebuf);
348 return JIM_ERR;
349 }
350
351 Jim_IncrRefCount(nameObjPtr);
352 valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
353 Jim_DecrRefCount(interp, nameObjPtr);
354 free(namebuf);
355 if (valObjPtr == NULL)
356 return JIM_ERR;
357
358 result = Jim_GetLong(interp, valObjPtr, &l);
359 /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
360 *val = l;
361 return result;
362 }
363
364 static int Jim_Command_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
365 {
366 target_t *target;
367 command_context_t *context;
368 long l;
369 u32 width;
370 u32 len;
371 u32 addr;
372 u32 count;
373 u32 v;
374 const char *varname;
375 u8 buffer[4096];
376 int i, n, e, retval;
377
378 /* argv[1] = name of array to get the data
379 * argv[2] = desired width
380 * argv[3] = memory address
381 * argv[4] = count to write
382 */
383 if (argc != 5) {
384 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
385 return JIM_ERR;
386 }
387 varname = Jim_GetString(argv[1], &len);
388 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
389
390 e = Jim_GetLong(interp, argv[2], &l);
391 width = l;
392 if (e != JIM_OK) {
393 return e;
394 }
395
396 e = Jim_GetLong(interp, argv[3], &l);
397 addr = l;
398 if (e != JIM_OK) {
399 return e;
400 }
401 e = Jim_GetLong(interp, argv[4], &l);
402 len = l;
403 if (e != JIM_OK) {
404 return e;
405 }
406 switch (width) {
407 case 8:
408 width = 1;
409 break;
410 case 16:
411 width = 2;
412 break;
413 case 32:
414 width = 4;
415 break;
416 default:
417 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
418 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
419 return JIM_ERR;
420 }
421 if (len == 0) {
422 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
423 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
424 return JIM_ERR;
425 }
426 if ((addr + (len * width)) < addr) {
427 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
428 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
429 return JIM_ERR;
430 }
431 /* absurd transfer size? */
432 if (len > 65536) {
433 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
434 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
435 return JIM_ERR;
436 }
437
438 if ((width == 1) ||
439 ((width == 2) && ((addr & 1) == 0)) ||
440 ((width == 4) && ((addr & 3) == 0))) {
441 /* all is well */
442 } else {
443 char buf[100];
444 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
445 sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);
446 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
447 return JIM_ERR;
448 }
449
450 context = Jim_GetAssocData(interp, "context");
451 if (context == NULL)
452 {
453 LOG_ERROR("array2mem: no command context");
454 return JIM_ERR;
455 }
456 target = get_current_target(context);
457 if (target == NULL)
458 {
459 LOG_ERROR("array2mem: no current target");
460 return JIM_ERR;
461 }
462
463 /* Transfer loop */
464
465 /* index counter */
466 n = 0;
467 /* assume ok */
468 e = JIM_OK;
469 while (len) {
470 /* Slurp... in buffer size chunks */
471
472 count = len; /* in objects.. */
473 if (count > (sizeof(buffer)/width)) {
474 count = (sizeof(buffer)/width);
475 }
476
477 v = 0; /* shut up gcc */
478 for (i = 0 ;i < count ;i++, n++) {
479 get_int_array_element(interp, varname, n, &v);
480 switch (width) {
481 case 4:
482 target_buffer_set_u32(target, &buffer[i*width], v);
483 break;
484 case 2:
485 target_buffer_set_u16(target, &buffer[i*width], v);
486 break;
487 case 1:
488 buffer[i] = v & 0x0ff;
489 break;
490 }
491 }
492 len -= count;
493
494 retval = target->type->write_memory(target, addr, width, count, buffer);
495 if (retval != ERROR_OK) {
496 /* BOO !*/
497 LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
498 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
499 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
500 e = JIM_ERR;
501 len = 0;
502 }
503 }
504
505 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
506
507 return JIM_OK;
508 }
509
510
511
512 /* find full path to file */
513 static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
514 {
515 if (argc != 2)
516 return JIM_ERR;
517 const char *file = Jim_GetString(argv[1], NULL);
518 char *full_path = find_file(file);
519 if (full_path == NULL)
520 return JIM_ERR;
521 Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
522 free(full_path);
523
524 Jim_SetResult(interp, result);
525 return JIM_OK;
526 }
527
528 static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
529 {
530 if (argc != 2)
531 return JIM_ERR;
532 const char *str = Jim_GetString(argv[1], NULL);
533 LOG_USER("%s", str);
534 return JIM_OK;
535 }
536
537
538
539 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
540 {
541 size_t nbytes;
542 const char *ptr;
543 Jim_Interp *interp;
544 command_context_t *context;
545
546 /* make it a char easier to read code */
547 ptr = _ptr;
548 interp = cookie;
549 nbytes = size * n;
550 if (ptr == NULL || interp == NULL || nbytes == 0) {
551 return 0;
552 }
553
554 context = Jim_GetAssocData(interp, "context");
555 if (context == NULL)
556 {
557 LOG_ERROR("openocd_jim_fwrite: no command context");
558 /* TODO: Where should this go? */
559 return n;
560 }
561
562 /* do we have to chunk it? */
563 if (ptr[nbytes] == 0)
564 {
565 /* no it is a C style string */
566 command_output_text(context, ptr);
567 return strlen(ptr);
568 }
569 /* GRR we must chunk - not null terminated */
570 while (nbytes) {
571 char chunk[128+1];
572 int x;
573
574 x = nbytes;
575 if (x > 128) {
576 x = 128;
577 }
578 /* copy it */
579 memcpy(chunk, ptr, x);
580 /* terminate it */
581 chunk[n] = 0;
582 /* output it */
583 command_output_text(context, chunk);
584 ptr += x;
585 nbytes -= x;
586 }
587
588 return n;
589 }
590
591 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie)
592 {
593 /* TCL wants to read... tell him no */
594 return 0;
595 }
596
597 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
598 {
599 char *cp;
600 int n;
601 Jim_Interp *interp;
602 command_context_t *context;
603
604 n = -1;
605 interp = cookie;
606 if (interp == NULL)
607 return n;
608
609 context = Jim_GetAssocData(interp, "context");
610 if (context == NULL)
611 {
612 LOG_ERROR("openocd_jim_vfprintf: no command context");
613 return n;
614 }
615
616 cp = alloc_vprintf(fmt, ap);
617 if (cp)
618 {
619 command_output_text(context, cp);
620 n = strlen(cp);
621 free(cp);
622 }
623 return n;
624 }
625
626 static int openocd_jim_fflush(void *cookie)
627 {
628 /* nothing to flush */
629 return 0;
630 }
631
632 static char* openocd_jim_fgets(char *s, int size, void *cookie)
633 {
634 /* not supported */
635 errno = ENOTSUP;
636 return NULL;
637 }
638
639 void add_jim(const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help)
640 {
641 Jim_CreateCommand(interp, name, cmd, NULL, NULL);
642
643 /* FIX!!! it would be prettier to invoke add_help_text...
644 accumulate help text in Tcl helptext list. */
645 Jim_Obj *helptext=Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
646 if (Jim_IsShared(helptext))
647 helptext = Jim_DuplicateObj(interp, helptext);
648
649 Jim_Obj *cmd_entry=Jim_NewListObj(interp, NULL, 0);
650
651 Jim_Obj *cmd_list=Jim_NewListObj(interp, NULL, 0);
652 Jim_ListAppendElement(interp, cmd_list, Jim_NewStringObj(interp, name, -1));
653
654 Jim_ListAppendElement(interp, cmd_entry, cmd_list);
655 Jim_ListAppendElement(interp, cmd_entry, Jim_NewStringObj(interp, help, -1));
656 Jim_ListAppendElement(interp, helptext, cmd_entry);
657 }
658
659 extern unsigned const char startup_tcl[];
660
661 void initJim(void)
662 {
663 Jim_CreateCommand(interp, "openocd_find", Jim_Command_find, NULL, NULL);
664 Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
665 Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
666 Jim_CreateCommand(interp, "array2mem", Jim_Command_array2mem, NULL, NULL );
667
668 /* Set Jim's STDIO */
669 interp->cookie_stdin = interp;
670 interp->cookie_stdout = interp;
671 interp->cookie_stderr = interp;
672 interp->cb_fwrite = openocd_jim_fwrite;
673 interp->cb_fread = openocd_jim_fread ;
674 interp->cb_vfprintf = openocd_jim_vfprintf;
675 interp->cb_fflush = openocd_jim_fflush;
676 interp->cb_fgets = openocd_jim_fgets;
677
678 add_default_dirs();
679
680 if (Jim_Eval(interp, startup_tcl)==JIM_ERR)
681 {
682 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
683 Jim_PrintErrorMessage(interp);
684 exit(-1);
685 }
686 }
687
688 command_context_t *setup_command_handler(void)
689 {
690 command_context_t *cmd_ctx;
691
692 cmd_ctx = command_init();
693
694 register_command(cmd_ctx, NULL, "version", handle_version_command,
695 COMMAND_EXEC, "show OpenOCD version");
696 register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG,
697 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
698
699 /* register subsystem commands */
700 server_register_commands(cmd_ctx);
701 telnet_register_commands(cmd_ctx);
702 gdb_register_commands(cmd_ctx);
703 tcl_register_commands(cmd_ctx); /* tcl server commands */
704 log_register_commands(cmd_ctx);
705 jtag_register_commands(cmd_ctx);
706 xsvf_register_commands(cmd_ctx);
707 target_register_commands(cmd_ctx);
708 flash_register_commands(cmd_ctx);
709 nand_register_commands(cmd_ctx);
710 pld_register_commands(cmd_ctx);
711
712 if (log_init(cmd_ctx) != ERROR_OK)
713 {
714 exit(-1);
715 }
716 LOG_DEBUG("log init complete");
717
718 LOG_OUTPUT( OPENOCD_VERSION "\n" );
719
720 register_command(cmd_ctx, NULL, "init", handle_init_command,
721 COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
722
723 return cmd_ctx;
724 }
725
726 /* normally this is the main() function entry, but if OpenOCD is linked
727 * into application, then this fn will not be invoked, but rather that
728 * application will have it's own implementation of main(). */
729 int openocd_main(int argc, char *argv[])
730 {
731 #ifdef JIM_EMBEDDED
732 Jim_InitEmbedded();
733 /* Create an interpreter */
734 interp = Jim_CreateInterp();
735 /* Add all the Jim core commands */
736 Jim_RegisterCoreCommands(interp);
737 #endif
738
739 initJim();
740
741 /* initialize commandline interface */
742 command_context_t *cmd_ctx;
743 cmd_ctx=setup_command_handler();
744
745 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
746 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
747 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
748 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
749 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
750 LOG_OUTPUT( "$URL$\n");
751 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
752 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
753 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
754 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
755 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
756
757 command_context_mode(cmd_ctx, COMMAND_CONFIG);
758 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
759
760 if (parse_cmdline_args(cmd_ctx, argc, argv) != ERROR_OK)
761 return EXIT_FAILURE;
762
763 if (parse_config_file(cmd_ctx) != ERROR_OK)
764 return EXIT_FAILURE;
765
766 command_context_mode(cmd_ctx, COMMAND_EXEC);
767 if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
768 return EXIT_FAILURE;
769
770 if (daemon_startup)
771 command_run_line(cmd_ctx, "reset");
772
773 /* handle network connections */
774 server_loop(cmd_ctx);
775
776 /* shut server down */
777 server_quit();
778
779 unregister_all_commands(cmd_ctx);
780
781 /* free commandline interface */
782 command_done(cmd_ctx);
783
784 return EXIT_SUCCESS;
785 }

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)