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