1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
21 #define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV
30 #include "configuration.h"
39 #include "telnet_server.h"
40 #include "gdb_server.h"
41 #include "tcl_server.h"
44 #include <sys/types.h>
59 /* Jim is provied by eCos */
60 #include <cyg/jimtcl/jim.h>
66 #include "replacements.h"
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
)
72 command_print(cmd_ctx
, OPENOCD_VERSION
);
77 static int daemon_startup
= 0;
79 int handle_daemon_startup_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
84 return ERROR_COMMAND_SYNTAX_ERROR
;
86 daemon_startup
= strcmp("reset", args
[0])==0;
88 command_print(cmd_ctx
, OPENOCD_VERSION
);
93 void exit_handler(void)
95 /* close JTAG interface */
96 if (jtag
&& jtag
->quit
)
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
)
104 static int initialized
=0;
110 atexit(exit_handler
);
112 if (target_init(cmd_ctx
) != ERROR_OK
)
114 LOG_DEBUG("target init complete");
116 if ((retval
=jtag_interface_init(cmd_ctx
)) != ERROR_OK
)
118 /* we must be able to set up the jtag interface */
121 LOG_DEBUG("jtag interface init complete");
123 /* Try to initialize & examine the JTAG chain at this point, but
124 * continue startup regardless */
125 if (jtag_init(cmd_ctx
) == ERROR_OK
)
127 LOG_DEBUG("jtag init complete");
128 if (target_examine(cmd_ctx
) == ERROR_OK
)
130 LOG_DEBUG("jtag examine complete");
134 if (flash_init_drivers(cmd_ctx
) != ERROR_OK
)
136 LOG_DEBUG("flash init complete");
138 if (nand_init(cmd_ctx
) != ERROR_OK
)
140 LOG_DEBUG("NAND init complete");
142 if (pld_init(cmd_ctx
) != ERROR_OK
)
144 LOG_DEBUG("pld init complete");
146 /* initialize tcp server */
149 /* initialize telnet subsystem */
150 telnet_init("Open On-Chip Debugger");
152 tcl_init(); /* allows tcl to just connect without going thru telnet */
158 command_context_t
*active_cmd_ctx
;
160 static int new_int_array_element(Jim_Interp
* interp
, const char *varname
, int idx
, u32 val
)
163 Jim_Obj
*nameObjPtr
, *valObjPtr
;
166 namebuf
= alloc_printf("%s(%d)", varname
, idx
);
170 nameObjPtr
= Jim_NewStringObj(interp
, namebuf
, -1);
171 valObjPtr
= Jim_NewIntObj(interp
, val
);
172 if (!nameObjPtr
|| !valObjPtr
)
178 Jim_IncrRefCount(nameObjPtr
);
179 Jim_IncrRefCount(valObjPtr
);
180 result
= Jim_SetVariable(interp
, nameObjPtr
, valObjPtr
);
181 Jim_DecrRefCount(interp
, nameObjPtr
);
182 Jim_DecrRefCount(interp
, valObjPtr
);
184 /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
188 static int Jim_Command_mem2array(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
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
207 Jim_WrongNumArgs(interp
, 1, argv
, "varname width addr nelems");
210 varname
= Jim_GetString(argv
[1], &len
);
211 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
213 e
= Jim_GetLong(interp
, argv
[2], &l
);
219 e
= Jim_GetLong(interp
, argv
[3], &l
);
224 e
= Jim_GetLong(interp
, argv
[4], &l
);
240 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
241 Jim_AppendStrings( interp
, Jim_GetResult(interp
), "Invalid width param, must be 8/16/32", NULL
);
245 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
246 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: zero width read?", NULL
);
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
);
254 /* absurd transfer size? */
256 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
257 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: absurd > 64K item request", NULL
);
262 ((width
== 2) && ((addr
& 1) == 0)) ||
263 ((width
== 4) && ((addr
& 3) == 0))) {
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
);
273 target
= get_current_target(active_cmd_ctx
);
282 /* Slurp... in buffer size chunks */
284 count
= len
; /* in objects.. */
285 if (count
> (sizeof(buffer
)/width
)) {
286 count
= (sizeof(buffer
)/width
);
289 retval
= target
->type
->read_memory( target
, addr
, width
, count
, buffer
);
290 if (retval
!= ERROR_OK
) {
292 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr
, width
, count
);
293 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
294 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: cannot read memory", NULL
);
298 v
= 0; /* shut up gcc */
299 for (i
= 0 ;i
< count
;i
++, n
++) {
302 v
= target_buffer_get_u32(target
, &buffer
[i
*width
]);
305 v
= target_buffer_get_u16(target
, &buffer
[i
*width
]);
308 v
= buffer
[i
] & 0x0ff;
311 new_int_array_element(interp
, varname
, n
, v
);
317 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
322 static int get_int_array_element(Jim_Interp
* interp
, const char *varname
, int idx
, u32
*val
)
325 Jim_Obj
*nameObjPtr
, *valObjPtr
;
329 namebuf
= alloc_printf("%s(%d)", varname
, idx
);
333 nameObjPtr
= Jim_NewStringObj(interp
, namebuf
, -1);
340 Jim_IncrRefCount(nameObjPtr
);
341 valObjPtr
= Jim_GetVariable(interp
, nameObjPtr
, JIM_ERRMSG
);
342 Jim_DecrRefCount(interp
, nameObjPtr
);
344 if (valObjPtr
== NULL
)
347 result
= Jim_GetLong(interp
, valObjPtr
, &l
);
348 /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
353 static int Jim_Command_array2mem(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
366 /* argv[1] = name of array to get the data
367 * argv[2] = desired width
368 * argv[3] = memory address
369 * argv[4] = count to write
372 Jim_WrongNumArgs(interp
, 1, argv
, "varname width addr nelems");
375 varname
= Jim_GetString(argv
[1], &len
);
376 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
378 e
= Jim_GetLong(interp
, argv
[2], &l
);
384 e
= Jim_GetLong(interp
, argv
[3], &l
);
389 e
= Jim_GetLong(interp
, argv
[4], &l
);
405 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
406 Jim_AppendStrings( interp
, Jim_GetResult(interp
), "Invalid width param, must be 8/16/32", NULL
);
410 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
411 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: zero width read?", NULL
);
414 if ((addr
+ (len
* width
)) < addr
) {
415 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
416 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: addr + len - wraps to zero?", NULL
);
419 /* absurd transfer size? */
421 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
422 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: absurd > 64K item request", NULL
);
427 ((width
== 2) && ((addr
& 1) == 0)) ||
428 ((width
== 4) && ((addr
& 3) == 0))) {
432 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
433 sprintf(buf
, "array2mem address: 0x%08x is not aligned for %d byte reads", addr
, width
);
434 Jim_AppendStrings(interp
, Jim_GetResult(interp
), buf
, NULL
);
438 target
= get_current_target(active_cmd_ctx
);
447 /* Slurp... in buffer size chunks */
449 count
= len
; /* in objects.. */
450 if (count
> (sizeof(buffer
)/width
)) {
451 count
= (sizeof(buffer
)/width
);
454 v
= 0; /* shut up gcc */
455 for (i
= 0 ;i
< count
;i
++, n
++) {
456 get_int_array_element(interp
, varname
, n
, &v
);
459 target_buffer_set_u32(target
, &buffer
[i
*width
], v
);
462 target_buffer_set_u16(target
, &buffer
[i
*width
], v
);
465 buffer
[i
] = v
& 0x0ff;
471 retval
= target
->type
->write_memory(target
, addr
, width
, count
, buffer
);
472 if (retval
!= ERROR_OK
) {
474 LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr
, width
, count
);
475 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
476 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: cannot read memory", NULL
);
482 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
488 static int openocd_retval
;
490 /* try to execute as Jim command, otherwise fall back to standard command.
491 * Note that even if the Jim command caused an error, then we succeeded
492 * to execute it, hence this fn pretty much always returns ERROR_OK. */
493 int jim_command(command_context_t
*context
, char *line
)
498 active_cmd_ctx
= context
;
499 openocd_retval
=ERROR_OK
;
500 retcode
= Jim_Eval(interp
, line
);
502 if (retcode
== JIM_ERR
) {
503 if (openocd_retval
!=ERROR_COMMAND_CLOSE_CONNECTION
)
505 /* We do not print the connection closed error message */
506 Jim_PrintErrorMessage(interp
);
508 if (openocd_retval
==ERROR_OK
)
510 /* It wasn't a low level OpenOCD command that failed */
513 return openocd_retval
;
517 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
519 if (retcode
== JIM_EXIT
) {
521 /* exit(Jim_GetExitCode(interp)); */
526 for (i
= 0; i
< reslen
; i
+= 256)
532 strncpy(buff
, result
+i
, chunk
);
534 LOG_USER_N("%s", buff
);
536 LOG_USER_N("%s", "\n");
542 /* find full path to file */
543 static int Jim_Command_find(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
547 const char *file
= Jim_GetString(argv
[1], NULL
);
548 char *full_path
= find_file(file
);
549 if (full_path
== NULL
)
551 Jim_Obj
*result
= Jim_NewStringObj(interp
, full_path
, strlen(full_path
));
554 Jim_SetResult(interp
, result
);
558 static int Jim_Command_echo(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
562 char *str
= (char*)Jim_GetString(argv
[1], NULL
);
569 static size_t openocd_jim_fwrite(const void *_ptr
, size_t size
, size_t n
, void *cookie
)
574 /* make it a char easier to read code */
582 if (!active_cmd_ctx
) {
583 /* TODO: Where should this go? */
587 /* do we have to chunk it? */
588 if (ptr
[nbytes
] == 0) {
589 /* no it is a C style string */
590 command_output_text(active_cmd_ctx
, ptr
);
593 /* GRR we must chunk - not null terminated */
603 memcpy(chunk
, ptr
, x
);
607 command_output_text(active_cmd_ctx
, chunk
);
615 static size_t openocd_jim_fread(void *ptr
, size_t size
, size_t n
, void *cookie
)
617 /* TCL wants to read... tell him no */
621 static int openocd_jim_vfprintf(void *cookie
, const char *fmt
, va_list ap
)
627 if (active_cmd_ctx
) {
628 cp
= alloc_vprintf(fmt
, ap
);
630 command_output_text(active_cmd_ctx
, cp
);
638 static int openocd_jim_fflush(void *cookie
)
640 /* nothing to flush */
644 static char* openocd_jim_fgets(char *s
, int size
, void *cookie
)
651 void add_jim(const char *name
, int (*cmd
)(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
), const char *help
)
653 Jim_CreateCommand(interp
, name
, cmd
, NULL
, NULL
);
655 /* FIX!!! it would be prettier to invoke add_help_text...
656 accumulate help text in Tcl helptext list. */
657 Jim_Obj
*helptext
=Jim_GetGlobalVariableStr(interp
, "ocd_helptext", JIM_ERRMSG
);
658 if (Jim_IsShared(helptext
))
659 helptext
= Jim_DuplicateObj(interp
, helptext
);
661 Jim_Obj
*cmd_entry
=Jim_NewListObj(interp
, NULL
, 0);
663 Jim_Obj
*cmd_list
=Jim_NewListObj(interp
, NULL
, 0);
664 Jim_ListAppendElement(interp
, cmd_list
, Jim_NewStringObj(interp
, name
, -1));
666 Jim_ListAppendElement(interp
, cmd_entry
, cmd_list
);
667 Jim_ListAppendElement(interp
, cmd_entry
, Jim_NewStringObj(interp
, help
, -1));
668 Jim_ListAppendElement(interp
, helptext
, cmd_entry
);
671 extern unsigned const char startup_tcl
[];
675 Jim_CreateCommand(interp
, "openocd_find", Jim_Command_find
, NULL
, NULL
);
676 Jim_CreateCommand(interp
, "echo", Jim_Command_echo
, NULL
, NULL
);
677 Jim_CreateCommand(interp
, "mem2array", Jim_Command_mem2array
, NULL
, NULL
);
678 Jim_CreateCommand(interp
, "array2mem", Jim_Command_array2mem
, NULL
, NULL
);
680 /* Set Jim's STDIO */
681 interp
->cookie_stdin
= NULL
;
682 interp
->cookie_stdout
= NULL
;
683 interp
->cookie_stderr
= NULL
;
684 interp
->cb_fwrite
= openocd_jim_fwrite
;
685 interp
->cb_fread
= openocd_jim_fread
;
686 interp
->cb_vfprintf
= openocd_jim_vfprintf
;
687 interp
->cb_fflush
= openocd_jim_fflush
;
688 interp
->cb_fgets
= openocd_jim_fgets
;
692 if (Jim_Eval(interp
, startup_tcl
)==JIM_ERR
)
694 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
695 Jim_PrintErrorMessage(interp
);
700 command_context_t
*setup_command_handler(void)
702 command_context_t
*cmd_ctx
;
704 cmd_ctx
= command_init();
706 register_command(cmd_ctx
, NULL
, "version", handle_version_command
,
707 COMMAND_EXEC
, "show OpenOCD version");
708 register_command(cmd_ctx
, NULL
, "daemon_startup", handle_daemon_startup_command
, COMMAND_CONFIG
,
709 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
711 /* register subsystem commands */
712 server_register_commands(cmd_ctx
);
713 telnet_register_commands(cmd_ctx
);
714 gdb_register_commands(cmd_ctx
);
715 tcl_register_commands(cmd_ctx
); /* tcl server commands */
716 log_register_commands(cmd_ctx
);
717 jtag_register_commands(cmd_ctx
);
718 xsvf_register_commands(cmd_ctx
);
719 target_register_commands(cmd_ctx
);
720 flash_register_commands(cmd_ctx
);
721 nand_register_commands(cmd_ctx
);
722 pld_register_commands(cmd_ctx
);
724 if (log_init(cmd_ctx
) != ERROR_OK
)
728 LOG_DEBUG("log init complete");
730 LOG_OUTPUT( OPENOCD_VERSION
"\n" );
733 register_command(cmd_ctx
, NULL
, "init", handle_init_command
,
734 COMMAND_ANY
, "initializes target and servers - nop on subsequent invocations");
739 /* normally this is the main() function entry, but if OpenOCD is linked
740 * into application, then this fn will not be invoked, but rather that
741 * application will have it's own implementation of main(). */
742 int openocd_main(int argc
, char *argv
[])
746 /* Create an interpreter */
747 interp
= Jim_CreateInterp();
748 /* Add all the Jim core commands */
749 Jim_RegisterCoreCommands(interp
);
754 /* initialize commandline interface */
755 command_context_t
*cmd_ctx
;
756 cmd_ctx
=setup_command_handler();
758 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
759 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
760 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
761 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
762 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
763 LOG_OUTPUT( "$URL$\n");
764 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
765 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
766 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
767 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
768 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
770 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
771 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
773 if (parse_cmdline_args(cmd_ctx
, argc
, argv
) != ERROR_OK
)
776 if (parse_config_file(cmd_ctx
) != ERROR_OK
)
779 command_context_mode(cmd_ctx
, COMMAND_EXEC
);
780 if (command_run_line(cmd_ctx
, "init")!=ERROR_OK
)
784 command_run_line(cmd_ctx
, "reset");
786 /* handle network connections */
787 server_loop(cmd_ctx
);
789 /* shut server down */
792 unregister_all_commands(cmd_ctx
);
794 /* free commandline interface */
795 command_done(cmd_ctx
);
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)