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 */
159 static int new_int_array_element(Jim_Interp
* interp
, const char *varname
, int idx
, u32 val
)
162 Jim_Obj
*nameObjPtr
, *valObjPtr
;
165 namebuf
= alloc_printf("%s(%d)", varname
, idx
);
169 nameObjPtr
= Jim_NewStringObj(interp
, namebuf
, -1);
170 valObjPtr
= Jim_NewIntObj(interp
, val
);
171 if (!nameObjPtr
|| !valObjPtr
)
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
);
183 /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
187 static int Jim_Command_mem2array(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
190 command_context_t
*context
;
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 context
= Jim_GetAssocData(interp
, "context");
276 LOG_ERROR("mem2array: no command context");
279 target
= get_current_target(context
);
282 LOG_ERROR("mem2array: no current target");
293 /* Slurp... in buffer size chunks */
295 count
= len
; /* in objects.. */
296 if (count
> (sizeof(buffer
)/width
)) {
297 count
= (sizeof(buffer
)/width
);
300 retval
= target
->type
->read_memory( target
, addr
, width
, count
, buffer
);
301 if (retval
!= ERROR_OK
) {
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
);
309 v
= 0; /* shut up gcc */
310 for (i
= 0 ;i
< count
;i
++, n
++) {
313 v
= target_buffer_get_u32(target
, &buffer
[i
*width
]);
316 v
= target_buffer_get_u16(target
, &buffer
[i
*width
]);
319 v
= buffer
[i
] & 0x0ff;
322 new_int_array_element(interp
, varname
, n
, v
);
328 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
333 static int get_int_array_element(Jim_Interp
* interp
, const char *varname
, int idx
, u32
*val
)
336 Jim_Obj
*nameObjPtr
, *valObjPtr
;
340 namebuf
= alloc_printf("%s(%d)", varname
, idx
);
344 nameObjPtr
= Jim_NewStringObj(interp
, namebuf
, -1);
351 Jim_IncrRefCount(nameObjPtr
);
352 valObjPtr
= Jim_GetVariable(interp
, nameObjPtr
, JIM_ERRMSG
);
353 Jim_DecrRefCount(interp
, nameObjPtr
);
355 if (valObjPtr
== NULL
)
358 result
= Jim_GetLong(interp
, valObjPtr
, &l
);
359 /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
364 static int Jim_Command_array2mem(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
367 command_context_t
*context
;
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
384 Jim_WrongNumArgs(interp
, 1, argv
, "varname width addr nelems");
387 varname
= Jim_GetString(argv
[1], &len
);
388 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
390 e
= Jim_GetLong(interp
, argv
[2], &l
);
396 e
= Jim_GetLong(interp
, argv
[3], &l
);
401 e
= Jim_GetLong(interp
, argv
[4], &l
);
417 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
418 Jim_AppendStrings( interp
, Jim_GetResult(interp
), "Invalid width param, must be 8/16/32", NULL
);
422 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
423 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: zero width read?", NULL
);
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
);
431 /* absurd transfer size? */
433 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
434 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: absurd > 64K item request", NULL
);
439 ((width
== 2) && ((addr
& 1) == 0)) ||
440 ((width
== 4) && ((addr
& 3) == 0))) {
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
);
450 context
= Jim_GetAssocData(interp
, "context");
453 LOG_ERROR("array2mem: no command context");
456 target
= get_current_target(context
);
459 LOG_ERROR("array2mem: no current target");
470 /* Slurp... in buffer size chunks */
472 count
= len
; /* in objects.. */
473 if (count
> (sizeof(buffer
)/width
)) {
474 count
= (sizeof(buffer
)/width
);
477 v
= 0; /* shut up gcc */
478 for (i
= 0 ;i
< count
;i
++, n
++) {
479 get_int_array_element(interp
, varname
, n
, &v
);
482 target_buffer_set_u32(target
, &buffer
[i
*width
], v
);
485 target_buffer_set_u16(target
, &buffer
[i
*width
], v
);
488 buffer
[i
] = v
& 0x0ff;
494 retval
= target
->type
->write_memory(target
, addr
, width
, count
, buffer
);
495 if (retval
!= ERROR_OK
) {
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
);
505 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
512 /* find full path to file */
513 static int Jim_Command_find(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
517 const char *file
= Jim_GetString(argv
[1], NULL
);
518 char *full_path
= find_file(file
);
519 if (full_path
== NULL
)
521 Jim_Obj
*result
= Jim_NewStringObj(interp
, full_path
, strlen(full_path
));
524 Jim_SetResult(interp
, result
);
528 static int Jim_Command_echo(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
532 const char *str
= Jim_GetString(argv
[1], NULL
);
539 static size_t openocd_jim_fwrite(const void *_ptr
, size_t size
, size_t n
, void *cookie
)
544 command_context_t
*context
;
546 /* make it a char easier to read code */
550 if (ptr
== NULL
|| interp
== NULL
|| nbytes
== 0) {
554 context
= Jim_GetAssocData(interp
, "context");
557 LOG_ERROR("openocd_jim_fwrite: no command context");
558 /* TODO: Where should this go? */
562 /* do we have to chunk it? */
563 if (ptr
[nbytes
] == 0)
565 /* no it is a C style string */
566 command_output_text(context
, ptr
);
569 /* GRR we must chunk - not null terminated */
579 memcpy(chunk
, ptr
, x
);
583 command_output_text(context
, chunk
);
591 static size_t openocd_jim_fread(void *ptr
, size_t size
, size_t n
, void *cookie
)
593 /* TCL wants to read... tell him no */
597 static int openocd_jim_vfprintf(void *cookie
, const char *fmt
, va_list ap
)
602 command_context_t
*context
;
609 context
= Jim_GetAssocData(interp
, "context");
612 LOG_ERROR("openocd_jim_vfprintf: no command context");
616 cp
= alloc_vprintf(fmt
, ap
);
619 command_output_text(context
, cp
);
626 static int openocd_jim_fflush(void *cookie
)
628 /* nothing to flush */
632 static char* openocd_jim_fgets(char *s
, int size
, void *cookie
)
639 void add_jim(const char *name
, int (*cmd
)(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
), const char *help
)
641 Jim_CreateCommand(interp
, name
, cmd
, NULL
, NULL
);
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
);
649 Jim_Obj
*cmd_entry
=Jim_NewListObj(interp
, NULL
, 0);
651 Jim_Obj
*cmd_list
=Jim_NewListObj(interp
, NULL
, 0);
652 Jim_ListAppendElement(interp
, cmd_list
, Jim_NewStringObj(interp
, name
, -1));
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
);
659 extern unsigned const char startup_tcl
[];
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
);
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
;
680 if (Jim_Eval(interp
, startup_tcl
)==JIM_ERR
)
682 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
683 Jim_PrintErrorMessage(interp
);
688 command_context_t
*setup_command_handler(void)
690 command_context_t
*cmd_ctx
;
692 cmd_ctx
= command_init();
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");
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
);
712 if (log_init(cmd_ctx
) != ERROR_OK
)
716 LOG_DEBUG("log init complete");
718 LOG_OUTPUT( OPENOCD_VERSION
"\n" );
720 register_command(cmd_ctx
, NULL
, "init", handle_init_command
,
721 COMMAND_ANY
, "initializes target and servers - nop on subsequent invocations");
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
[])
733 /* Create an interpreter */
734 interp
= Jim_CreateInterp();
735 /* Add all the Jim core commands */
736 Jim_RegisterCoreCommands(interp
);
741 /* initialize commandline interface */
742 command_context_t
*cmd_ctx
;
743 cmd_ctx
=setup_command_handler();
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 */
757 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
758 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
760 if (parse_cmdline_args(cmd_ctx
, argc
, argv
) != ERROR_OK
)
763 if (parse_config_file(cmd_ctx
) != ERROR_OK
)
766 command_context_mode(cmd_ctx
, COMMAND_EXEC
);
767 if (command_run_line(cmd_ctx
, "init")!=ERROR_OK
)
771 command_run_line(cmd_ctx
, "reset");
773 /* handle network connections */
774 server_loop(cmd_ctx
);
776 /* shut server down */
779 unregister_all_commands(cmd_ctx
);
781 /* free commandline interface */
782 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)