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"
31 #include "interpreter.h"
40 #include "telnet_server.h"
41 #include "gdb_server.h"
44 #include <sys/types.h>
56 /* Give TELNET a way to find out what version this is */
57 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
59 command_print(cmd_ctx, OPENOCD_VERSION);
64 static int daemon_startup = 0;
66 int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
71 return ERROR_COMMAND_SYNTAX_ERROR;
73 daemon_startup = strcmp("reset", args[0])==0;
75 command_print(cmd_ctx, OPENOCD_VERSION);
81 void exit_handler(void)
83 /* close JTAG interface */
84 if (jtag && jtag->quit)
89 /* OpenOCD can't really handle failure of this command. Patches welcome! :-) */
90 int handle_init_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
93 static int initialized=0;
99 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
101 atexit(exit_handler);
104 if (target_init(cmd_ctx) != ERROR_OK)
106 LOG_DEBUG("target init complete");
108 if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
110 /* we must be able to set up the jtag interface */
113 LOG_DEBUG("jtag interface init complete");
115 /* Try to initialize & examine the JTAG chain at this point, but
116 * continue startup regardless
118 if (jtag_init(cmd_ctx) == ERROR_OK)
120 LOG_DEBUG("jtag init complete");
121 if (target_examine(cmd_ctx) == ERROR_OK)
123 LOG_DEBUG("jtag examine complete");
128 if (flash_init_drivers(cmd_ctx) != ERROR_OK)
130 LOG_DEBUG("flash init complete");
132 if (nand_init(cmd_ctx) != ERROR_OK)
134 LOG_DEBUG("NAND init complete");
136 if (pld_init(cmd_ctx) != ERROR_OK)
138 LOG_DEBUG("pld init complete");
140 /* initialize tcp server */
143 /* initialize telnet subsystem */
144 telnet_init("Open On-Chip Debugger");
146 tcl_init(); /* allows tcl to just connect without going thru telnet */
152 /* implementations of OpenOCD that uses multithreading needs to lock OpenOCD while calling
153 * OpenOCD fn's. No-op in vanilla OpenOCD
167 command_context_t *active_cmd_ctx;
170 new_int_array_element( Jim_Interp * interp,
176 Jim_Obj *nameObjPtr, *valObjPtr;
179 namebuf = alloca( strlen(varname) + 30 );
180 sprintf( namebuf, "%s(%d)", varname, idx );
183 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
184 valObjPtr = Jim_NewIntObj(interp, val );
185 Jim_IncrRefCount(nameObjPtr);
186 Jim_IncrRefCount(valObjPtr);
187 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
188 Jim_DecrRefCount(interp, nameObjPtr);
189 Jim_DecrRefCount(interp, valObjPtr);
190 // printf( "%s = 0%08x\n", namebuf, val );
195 Jim_Command_mem2array( Jim_Interp *interp, int argc, Jim_Obj *const *argv)
210 /* argv[1] = name of array to receive the data
211 * argv[2] = desired width
212 * argv[3] = memory address
213 * argv[4] = length in bytes to read
216 Jim_WrongNumArgs( interp, 1, argv, "varname width addr nelems" );
219 varname = Jim_GetString( argv[1], &len );
220 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
223 e = Jim_GetLong( interp, argv[2], &l );
229 e = Jim_GetLong( interp, argv[3], &l );
234 e = Jim_GetLong( interp, argv[4], &l );
250 Jim_SetResult(interp,
251 Jim_NewEmptyStringObj(interp));
252 Jim_AppendStrings( interp, Jim_GetResult(interp),
253 "Invalid width param, must be 8/16/32", NULL );
257 Jim_SetResult(interp,
258 Jim_NewEmptyStringObj(interp));
259 Jim_AppendStrings( interp, Jim_GetResult(interp),
260 "mem2array: zero width read?", NULL );
263 if( (addr + (len * width)) < addr ){
264 Jim_SetResult(interp,
265 Jim_NewEmptyStringObj(interp));
266 Jim_AppendStrings( interp, Jim_GetResult(interp),
267 "mem2array: addr + len - wraps to zero?", NULL );
270 /* absurd transfer size? */
272 Jim_SetResult(interp,
273 Jim_NewEmptyStringObj(interp));
274 Jim_AppendStrings( interp, Jim_GetResult(interp),
275 "mem2array: absurd > 64K item request", NULL );
280 ((width == 2) && ((addr & 1) == 0)) ||
281 ((width == 4) && ((addr & 3) == 0)) ){
285 Jim_SetResult(interp,
286 Jim_NewEmptyStringObj(interp));
288 "mem2array address: 0x%08x is not aligned for %d byte reads",
291 Jim_AppendStrings( interp, Jim_GetResult(interp),
296 target = get_current_target( active_cmd_ctx );
306 /* Slurp... in buffer size chunks */
308 count = len; /* in objects.. */
309 if( count > (sizeof(buffer)/width)){
310 count = (sizeof(buffer)/width);
313 retval = target->type->read_memory( target,
319 if( retval != ERROR_OK ){
321 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed",
322 addr, width, count );
323 Jim_SetResult(interp,
324 Jim_NewEmptyStringObj(interp));
325 Jim_AppendStrings( interp, Jim_GetResult(interp),
326 "mem2array: cannot read memory", NULL );
330 v = 0; /* shut up gcc */
331 for( i = 0 ; i < count ; i++, n++ ){
334 v = target_buffer_get_u32( target, &buffer[i*width] );
337 v = target_buffer_get_u16( target, &buffer[i*width] );
340 v = buffer[i] & 0x0ff;
343 new_int_array_element( interp, varname, n, v );
348 Jim_SetResult(interp,
349 Jim_NewEmptyStringObj(interp));
354 static void tcl_output(void *privData, const char *file, int line,
355 const char *function, const char *string)
357 Jim_Obj *tclOutput=(Jim_Obj *)privData;
359 Jim_AppendString(interp, tclOutput, string, strlen(string));
362 /* try to execute as Jim command, otherwise fall back to standard command.
364 Note that even if the Jim command caused an error, then we succeeded
365 to execute it, hence this fn pretty much always returns ERROR_OK.
368 int jim_command(command_context_t *context, char *line)
371 /* FIX!!!! in reality there is only one cmd_ctx handler, but consider
372 what might happen here if there are multiple handlers w/reentrant callback
374 active_cmd_ctx=context;
375 int retcode=Jim_Eval(interp, line);
379 result = Jim_GetString(Jim_GetResult(interp), &reslen);
380 if (retcode == JIM_ERR) {
383 LOG_USER_N("Runtime error, file \"%s\", line %d:" JIM_NL,
384 interp->errorFileName, interp->errorLine);
385 LOG_USER_N(" %s" JIM_NL,
386 Jim_GetString(interp->result, NULL));
387 Jim_ListLength(interp, interp->stackTrace, &len);
388 for (i = 0; i < len; i+= 3) {
390 const char *proc, *file, *line;
392 Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
393 proc = Jim_GetString(objPtr, NULL);
394 Jim_ListIndex(interp, interp->stackTrace, i+1, &objPtr,
396 file = Jim_GetString(objPtr, NULL);
397 Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr,
399 line = Jim_GetString(objPtr, NULL);
400 LOG_USER_N("In procedure '%s' called at file \"%s\", line %s" JIM_NL,
403 } else if (retcode == JIM_EXIT) {
405 //exit(Jim_GetExitCode(interp));
410 for (i=0; i<reslen; i+=256)
416 strncpy(buff, result, chunk);
418 LOG_USER_N("%s", buff);
420 LOG_USER_N("%s", "\n");
426 static int startLoop=0;
429 Jim_Command_openocd_ignore(Jim_Interp *interp,
431 Jim_Obj *const *argv,
435 char *cmd = (char*)Jim_GetString(argv[1], NULL);
439 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
443 // We don't know whether or not the telnet/gdb server is running...
444 target_call_timer_callbacks_now();
447 log_add_callback(tcl_output, tclOutput);
448 retval=command_run_line_internal(active_cmd_ctx, cmd);
452 target_call_timer_callbacks_now();
454 log_remove_callback(tcl_output, tclOutput);
456 Jim_SetResult(interp, tclOutput);
459 return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
463 Jim_Command_openocd(Jim_Interp *interp,
465 Jim_Obj *const *argv)
467 return Jim_Command_openocd_ignore(interp, argc, argv, 1);
471 Jim_Command_openocd_throw(Jim_Interp *interp,
473 Jim_Obj *const *argv)
475 return Jim_Command_openocd_ignore(interp, argc, argv, 0);
481 /* find full path to file */
483 Jim_Command_find(Jim_Interp *interp,
485 Jim_Obj *const *argv)
489 char *file = (char*)Jim_GetString(argv[1], NULL);
490 char *full_path=find_file(file);
493 Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
496 Jim_SetResult(interp, result);
501 Jim_Command_echo(Jim_Interp *interp,
503 Jim_Obj *const *argv)
507 char *str = (char*)Jim_GetString(argv[1], NULL);
513 openocd_jim_fwrite( const void *_ptr, size_t size, size_t n, void *cookie )
518 /* make it a char easier to read code */
526 if( !active_cmd_ctx ){
527 /* FIXME: Where should this go? */
532 /* do we have to chunk it? */
533 if( ptr[ nbytes ] == 0 ){
534 /* no it is a C style string */
535 command_output_text( active_cmd_ctx, ptr );
538 /* GRR we must chunk - not null terminated */
548 memcpy( chunk, ptr, x );
552 command_output_text( active_cmd_ctx, chunk );
561 openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
563 /* TCL wants to read... tell him no */
569 openocd_jim_vfprintf( void *cookie, const char *fmt, va_list ap )
575 if( active_cmd_ctx ){
576 cp = alloc_vprintf( fmt, ap );
578 command_output_text( active_cmd_ctx, cp );
587 openocd_jim_fflush( void *cookie )
589 /* nothing to flush */
594 openocd_jim_fgets( char *s, int size, void *cookie )
607 /* Create an interpreter */
608 interp = Jim_CreateInterp();
609 /* Add all the Jim core commands */
610 Jim_RegisterCoreCommands(interp);
611 Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
612 Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
613 Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
614 Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
615 Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
617 /* Set Jim's STDIO */
618 interp->cookie_stdin = NULL;
619 interp->cookie_stdout = NULL;
620 interp->cookie_stderr = NULL;
621 interp->cb_fwrite = openocd_jim_fwrite;
622 interp->cb_fread = openocd_jim_fread ;
623 interp->cb_vfprintf = openocd_jim_vfprintf;
624 interp->cb_fflush = openocd_jim_fflush;
625 interp->cb_fgets = openocd_jim_fgets;
628 int main(int argc, char *argv[])
632 /* initialize commandline interface */
633 command_context_t *cmd_ctx, *cfg_cmd_ctx;
634 cmd_ctx = command_init();
636 register_command(cmd_ctx, NULL, "version", handle_version_command,
637 COMMAND_EXEC, "show OpenOCD version");
638 register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG,
639 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
641 /* register subsystem commands */
642 server_register_commands(cmd_ctx);
643 telnet_register_commands(cmd_ctx);
644 gdb_register_commands(cmd_ctx);
645 tcl_register_commands(cmd_ctx); /* tcl server commands */
646 log_register_commands(cmd_ctx);
647 jtag_register_commands(cmd_ctx);
648 interpreter_register_commands(cmd_ctx);
649 xsvf_register_commands(cmd_ctx);
650 target_register_commands(cmd_ctx);
651 flash_register_commands(cmd_ctx);
652 nand_register_commands(cmd_ctx);
653 pld_register_commands(cmd_ctx);
655 if (log_init(cmd_ctx) != ERROR_OK)
657 LOG_DEBUG("log init complete");
659 LOG_OUTPUT( OPENOCD_VERSION "\n" );
662 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
663 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
664 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
665 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
666 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
667 LOG_OUTPUT( "$URL$\n");
668 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
669 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
670 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
671 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
672 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
674 register_command(cmd_ctx, NULL, "init", handle_init_command,
675 COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
677 cfg_cmd_ctx = copy_command_context(cmd_ctx);
678 cfg_cmd_ctx->mode = COMMAND_CONFIG;
679 command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
681 if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
684 Jim_Eval(interp, "source [find tcl/commands.tcl]");
686 if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
689 command_done(cfg_cmd_ctx);
691 if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
695 command_run_line(cmd_ctx, "reset");
700 /* handle network connections */
701 server_loop(cmd_ctx);
703 /* shut server down */
706 unregister_all_commands(cmd_ctx);
708 /* free commandline interface */
709 command_done(cmd_ctx);
716 * Local Variables: **
718 * c-basic-offset: 4 **