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);