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 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
112 atexit(exit_handler
);
114 if (target_init(cmd_ctx
) != ERROR_OK
)
116 LOG_DEBUG("target init complete");
118 if ((retval
=jtag_interface_init(cmd_ctx
)) != ERROR_OK
)
120 /* we must be able to set up the jtag interface */
123 LOG_DEBUG("jtag interface init complete");
125 /* Try to initialize & examine the JTAG chain at this point, but
126 * continue startup regardless */
127 if (jtag_init(cmd_ctx
) == ERROR_OK
)
129 LOG_DEBUG("jtag init complete");
130 if (target_examine(cmd_ctx
) == ERROR_OK
)
132 LOG_DEBUG("jtag examine complete");
136 if (flash_init_drivers(cmd_ctx
) != ERROR_OK
)
138 LOG_DEBUG("flash init complete");
140 if (nand_init(cmd_ctx
) != ERROR_OK
)
142 LOG_DEBUG("NAND init complete");
144 if (pld_init(cmd_ctx
) != ERROR_OK
)
146 LOG_DEBUG("pld init complete");
148 /* initialize tcp server */
151 /* initialize telnet subsystem */
152 telnet_init("Open On-Chip Debugger");
154 tcl_init(); /* allows tcl to just connect without going thru telnet */
160 command_context_t
*active_cmd_ctx
;
162 static int new_int_array_element(Jim_Interp
* interp
, const char *varname
, int idx
, u32 val
)
165 Jim_Obj
*nameObjPtr
, *valObjPtr
;
168 namebuf
= alloc_printf("%s(%d)", varname
, idx
);
172 nameObjPtr
= Jim_NewStringObj(interp
, namebuf
, -1);
173 valObjPtr
= Jim_NewIntObj(interp
, val
);
174 if (!nameObjPtr
|| !valObjPtr
)
180 Jim_IncrRefCount(nameObjPtr
);
181 Jim_IncrRefCount(valObjPtr
);
182 result
= Jim_SetVariable(interp
, nameObjPtr
, valObjPtr
);
183 Jim_DecrRefCount(interp
, nameObjPtr
);
184 Jim_DecrRefCount(interp
, valObjPtr
);
186 /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
190 static int Jim_Command_mem2array(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
203 /* argv[1] = name of array to receive the data
204 * argv[2] = desired width
205 * argv[3] = memory address
206 * argv[4] = count of times to read
209 Jim_WrongNumArgs(interp
, 1, argv
, "varname width addr nelems");
212 varname
= Jim_GetString(argv
[1], &len
);
213 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
215 e
= Jim_GetLong(interp
, argv
[2], &l
);
221 e
= Jim_GetLong(interp
, argv
[3], &l
);
226 e
= Jim_GetLong(interp
, argv
[4], &l
);
242 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
243 Jim_AppendStrings( interp
, Jim_GetResult(interp
), "Invalid width param, must be 8/16/32", NULL
);
247 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
248 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: zero width read?", NULL
);
251 if ((addr
+ (len
* width
)) < addr
) {
252 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
253 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: addr + len - wraps to zero?", NULL
);
256 /* absurd transfer size? */
258 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
259 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: absurd > 64K item request", NULL
);
264 ((width
== 2) && ((addr
& 1) == 0)) ||
265 ((width
== 4) && ((addr
& 3) == 0))) {
269 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
270 sprintf(buf
, "mem2array address: 0x%08x is not aligned for %d byte reads", addr
, width
);
271 Jim_AppendStrings(interp
, Jim_GetResult(interp
), buf
, NULL
);
275 target
= get_current_target(active_cmd_ctx
);
284 /* Slurp... in buffer size chunks */
286 count
= len
; /* in objects.. */
287 if (count
> (sizeof(buffer
)/width
)) {
288 count
= (sizeof(buffer
)/width
);
291 retval
= target
->type
->read_memory( target
, addr
, width
, count
, buffer
);
292 if (retval
!= ERROR_OK
) {
294 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr
, width
, count
);
295 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
296 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: cannot read memory", NULL
);
300 v
= 0; /* shut up gcc */
301 for (i
= 0 ;i
< count
;i
++, n
++) {
304 v
= target_buffer_get_u32(target
, &buffer
[i
*width
]);
307 v
= target_buffer_get_u16(target
, &buffer
[i
*width
]);
310 v
= buffer
[i
] & 0x0ff;
313 new_int_array_element(interp
, varname
, n
, v
);
319 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
324 static int get_int_array_element(Jim_Interp
* interp
, const char *varname
, int idx
, u32
*val
)
327 Jim_Obj
*nameObjPtr
, *valObjPtr
;
331 namebuf
= alloc_printf("%s(%d)", varname
, idx
);
335 nameObjPtr
= Jim_NewStringObj(interp
, namebuf
, -1);
342 Jim_IncrRefCount(nameObjPtr
);
343 valObjPtr
= Jim_GetVariable(interp
, nameObjPtr
, JIM_ERRMSG
);
344 Jim_DecrRefCount(interp
, nameObjPtr
);
346 if (valObjPtr
== NULL
)
349 result
= Jim_GetLong(interp
, valObjPtr
, &l
);
350 /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
355 static int Jim_Command_array2mem(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
368 /* argv[1] = name of array to get the data
369 * argv[2] = desired width
370 * argv[3] = memory address
371 * argv[4] = count to write
374 Jim_WrongNumArgs(interp
, 1, argv
, "varname width addr nelems");
377 varname
= Jim_GetString(argv
[1], &len
);
378 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
380 e
= Jim_GetLong(interp
, argv
[2], &l
);
386 e
= Jim_GetLong(interp
, argv
[3], &l
);
391 e
= Jim_GetLong(interp
, argv
[4], &l
);
407 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
408 Jim_AppendStrings( interp
, Jim_GetResult(interp
), "Invalid width param, must be 8/16/32", NULL
);
412 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
413 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: zero width read?", NULL
);
416 if ((addr
+ (len
* width
)) < addr
) {
417 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
418 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: addr + len - wraps to zero?", NULL
);
421 /* absurd transfer size? */
423 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
424 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "array2mem: absurd > 64K item request", NULL
);
429 ((width
== 2) && ((addr
& 1) == 0)) ||
430 ((width
== 4) && ((addr
& 3) == 0))) {
434 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
435 sprintf(buf
, "array2mem address: 0x%08x is not aligned for %d byte reads", addr
, width
);
436 Jim_AppendStrings(interp
, Jim_GetResult(interp
), buf
, NULL
);
440 target
= get_current_target(active_cmd_ctx
);
449 /* Slurp... in buffer size chunks */
451 count
= len
; /* in objects.. */
452 if (count
> (sizeof(buffer
)/width
)) {
453 count
= (sizeof(buffer
)/width
);
456 v
= 0; /* shut up gcc */
457 for (i
= 0 ;i
< count
;i
++, n
++) {
458 get_int_array_element(interp
, varname
, n
, &v
);
461 target_buffer_set_u32(target
, &buffer
[i
*width
], v
);
464 target_buffer_set_u16(target
, &buffer
[i
*width
], v
);
467 buffer
[i
] = v
& 0x0ff;
473 retval
= target
->type
->write_memory(target
, addr
, width
, count
, buffer
);
474 if (retval
!= ERROR_OK
) {
476 LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr
, width
, count
);
477 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
478 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "mem2array: cannot read memory", NULL
);
484 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
489 static void tcl_output(void *privData
, const char *file
, int line
, const char *function
, const char *string
)
491 Jim_Obj
*tclOutput
=(Jim_Obj
*)privData
;
493 Jim_AppendString(interp
, tclOutput
, string
, strlen(string
));
496 /* try to execute as Jim command, otherwise fall back to standard command.
497 * Note that even if the Jim command caused an error, then we succeeded
498 * to execute it, hence this fn pretty much always returns ERROR_OK. */
499 int jim_command(command_context_t
*context
, char *line
)
502 int retcode
=Jim_Eval(interp
, line
);
504 if (retcode
== JIM_ERR
) {
505 Jim_PrintErrorMessage(interp
);
507 Jim_Obj
*openocd_result
=Jim_GetVariableStr(interp
, "openocd_result", JIM_ERRMSG
);
510 if (Jim_GetLong(interp
, openocd_result
, &t
)==JIM_OK
)
519 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
521 if (retcode
== JIM_EXIT
) {
523 /* exit(Jim_GetExitCode(interp)); */
528 for (i
= 0; i
< reslen
; i
+= 256)
534 strncpy(buff
, result
+i
, chunk
);
536 LOG_USER_N("%s", buff
);
538 LOG_USER_N("%s", "\n");
546 static int Jim_Command_openocd_ignore(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
, int ignore
)
549 char *cmd
= (char*)Jim_GetString(argv
[1], NULL
);
551 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
555 /* We don't know whether or not the telnet/gdb server is running... */
556 target_call_timer_callbacks_now();
559 log_add_callback(tcl_output
, tclOutput
);
560 retval
=command_run_line_internal(active_cmd_ctx
, cmd
);
562 /* we need to be able to get at the retval, so we store in a variable
564 Jim_Obj
*resultvar
=Jim_NewIntObj(interp
, retval
);
565 Jim_IncrRefCount(resultvar
);
566 Jim_SetGlobalVariableStr(interp
, "openocd_result", resultvar
);
567 Jim_DecrRefCount(interp
, resultvar
);
571 target_call_timer_callbacks_now();
573 log_remove_callback(tcl_output
, tclOutput
);
575 Jim_SetResult(interp
, tclOutput
);
577 return (ignore
||(retval
==ERROR_OK
))?JIM_OK
:JIM_ERR
;
580 static int Jim_Command_openocd(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
582 return Jim_Command_openocd_ignore(interp
, argc
, argv
, 1);
585 static int Jim_Command_openocd_throw(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
587 return Jim_Command_openocd_ignore(interp
, argc
, argv
, 0);
590 /* find full path to file */
591 static int Jim_Command_find(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
595 char *file
= (char*)Jim_GetString(argv
[1], NULL
);
596 char *full_path
= find_file(file
);
597 if (full_path
== NULL
)
599 Jim_Obj
*result
= Jim_NewStringObj(interp
, full_path
, strlen(full_path
));
602 Jim_SetResult(interp
, result
);
606 static int Jim_Command_echo(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
610 char *str
= (char*)Jim_GetString(argv
[1], NULL
);
615 static size_t openocd_jim_fwrite(const void *_ptr
, size_t size
, size_t n
, void *cookie
)
620 /* make it a char easier to read code */
628 if (!active_cmd_ctx
) {
629 /* TODO: Where should this go? */
633 /* do we have to chunk it? */
634 if (ptr
[nbytes
] == 0) {
635 /* no it is a C style string */
636 command_output_text(active_cmd_ctx
, ptr
);
639 /* GRR we must chunk - not null terminated */
649 memcpy(chunk
, ptr
, x
);
653 command_output_text(active_cmd_ctx
, chunk
);
661 static size_t openocd_jim_fread(void *ptr
, size_t size
, size_t n
, void *cookie
)
663 /* TCL wants to read... tell him no */
667 static int openocd_jim_vfprintf(void *cookie
, const char *fmt
, va_list ap
)
673 if (active_cmd_ctx
) {
674 cp
= alloc_vprintf(fmt
, ap
);
676 command_output_text(active_cmd_ctx
, cp
);
684 static int openocd_jim_fflush(void *cookie
)
686 /* nothing to flush */
690 static char* openocd_jim_fgets(char *s
, int size
, void *cookie
)
697 void add_jim(const char *name
, int (*cmd
)(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
), const char *help
)
699 Jim_CreateCommand(interp
, name
, cmd
, NULL
, NULL
);
701 /* FIX!!! it would be prettier to invoke add_help_text...
702 accumulate help text in Tcl helptext list. */
703 Jim_Obj
*helptext
=Jim_GetGlobalVariableStr(interp
, "ocd_helptext", JIM_ERRMSG
);
704 Jim_Obj
*cmd_entry
=Jim_NewListObj(interp
, NULL
, 0);
706 Jim_Obj
*cmd_list
=Jim_NewListObj(interp
, NULL
, 0);
707 Jim_ListAppendElement(interp
, cmd_list
, Jim_NewStringObj(interp
, name
, -1));
709 Jim_ListAppendElement(interp
, cmd_entry
, cmd_list
);
710 Jim_ListAppendElement(interp
, cmd_entry
, Jim_NewStringObj(interp
, help
, -1));
711 Jim_ListAppendElement(interp
, helptext
, cmd_entry
);
714 extern const unsigned char filedata_startup
[];
718 Jim_CreateCommand(interp
, "openocd", Jim_Command_openocd
, NULL
, NULL
);
719 Jim_CreateCommand(interp
, "openocd_throw", Jim_Command_openocd_throw
, NULL
, NULL
);
720 Jim_CreateCommand(interp
, "find", Jim_Command_find
, NULL
, NULL
);
721 Jim_CreateCommand(interp
, "echo", Jim_Command_echo
, NULL
, NULL
);
722 Jim_CreateCommand(interp
, "mem2array", Jim_Command_mem2array
, NULL
, NULL
);
723 Jim_CreateCommand(interp
, "array2mem", Jim_Command_array2mem
, NULL
, NULL
);
725 /* Set Jim's STDIO */
726 interp
->cookie_stdin
= NULL
;
727 interp
->cookie_stdout
= NULL
;
728 interp
->cookie_stderr
= NULL
;
729 interp
->cb_fwrite
= openocd_jim_fwrite
;
730 interp
->cb_fread
= openocd_jim_fread
;
731 interp
->cb_vfprintf
= openocd_jim_vfprintf
;
732 interp
->cb_fflush
= openocd_jim_fflush
;
733 interp
->cb_fgets
= openocd_jim_fgets
;
737 if (Jim_Eval(interp
, filedata_startup
)==JIM_ERR
)
739 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
740 Jim_PrintErrorMessage(interp
);
747 int handle_script_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
752 return ERROR_COMMAND_SYNTAX_ERROR
;
755 /* Run a tcl script file */
756 return command_run_linef(cmd_ctx
, "source [find {%s}]", args
[0]);
759 command_context_t
*setup_command_handler(void)
761 command_context_t
*cmd_ctx
;
763 cmd_ctx
= command_init();
765 register_command(cmd_ctx
, NULL
, "version", handle_version_command
,
766 COMMAND_EXEC
, "show OpenOCD version");
767 register_command(cmd_ctx
, NULL
, "daemon_startup", handle_daemon_startup_command
, COMMAND_CONFIG
,
768 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
770 /* register subsystem commands */
771 server_register_commands(cmd_ctx
);
772 telnet_register_commands(cmd_ctx
);
773 gdb_register_commands(cmd_ctx
);
774 tcl_register_commands(cmd_ctx
); /* tcl server commands */
775 log_register_commands(cmd_ctx
);
776 jtag_register_commands(cmd_ctx
);
777 register_command(cmd_ctx
, NULL
, "script", handle_script_command
, COMMAND_ANY
, "execute commands from <file>");
778 xsvf_register_commands(cmd_ctx
);
779 target_register_commands(cmd_ctx
);
780 flash_register_commands(cmd_ctx
);
781 nand_register_commands(cmd_ctx
);
782 pld_register_commands(cmd_ctx
);
784 if (log_init(cmd_ctx
) != ERROR_OK
)
788 LOG_DEBUG("log init complete");
790 LOG_OUTPUT( OPENOCD_VERSION
"\n" );
793 register_command(cmd_ctx
, NULL
, "init", handle_init_command
,
794 COMMAND_ANY
, "initializes target and servers - nop on subsequent invocations");
799 /* normally this is the main() function entry, but if OpenOCD is linked
800 * into application, then this fn will not be invoked, but rather that
801 * application will have it's own implementation of main(). */
802 int openocd_main(int argc
, char *argv
[])
806 /* Create an interpreter */
807 interp
= Jim_CreateInterp();
808 /* Add all the Jim core commands */
809 Jim_RegisterCoreCommands(interp
);
814 /* initialize commandline interface */
815 command_context_t
*cmd_ctx
;
816 cmd_ctx
=setup_command_handler();
818 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
819 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
820 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
821 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
822 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
823 LOG_OUTPUT( "$URL$\n");
824 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
825 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
826 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
827 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
828 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
830 command_context_t
*cfg_cmd_ctx
;
831 cfg_cmd_ctx
= copy_command_context(cmd_ctx
);
832 cfg_cmd_ctx
->mode
= COMMAND_CONFIG
;
833 command_set_output_handler(cfg_cmd_ctx
, configuration_output_handler
, NULL
);
835 active_cmd_ctx
=cfg_cmd_ctx
;
838 if (parse_cmdline_args(cfg_cmd_ctx
, argc
, argv
) != ERROR_OK
)
841 if (parse_config_file(cfg_cmd_ctx
) != ERROR_OK
)
844 active_cmd_ctx
=cmd_ctx
;
846 command_done(cfg_cmd_ctx
);
848 if (command_run_line(cmd_ctx
, "init")!=ERROR_OK
)
852 command_run_line(cmd_ctx
, "reset");
856 /* handle network connections */
857 server_loop(cmd_ctx
);
859 /* shut server down */
862 unregister_all_commands(cmd_ctx
);
864 /* free commandline interface */
865 command_done(cmd_ctx
);