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"
42 #include "tcl_server.h"
45 #include <sys/types.h>
60 /* Jim is provied by eCos */
61 #include <cyg/jimtcl/jim.h>
67 #include "replacements.h"
69 int launchTarget(struct command_context_s *cmd_ctx)
72 /* Try to examine & validate jtag chain, though this may require a reset first
73 * in which case we continue setup */
76 /* try to examine target at this point. If it fails, perhaps a reset will
77 * bring it up later on via a telnet/gdb session */
78 target_examine(cmd_ctx);
80 retval=flash_init_drivers(cmd_ctx);
83 LOG_DEBUG("flash init complete");
85 retval=nand_init(cmd_ctx);
88 LOG_DEBUG("NAND init complete");
90 retval=pld_init(cmd_ctx);
93 LOG_DEBUG("pld init complete");
97 /* Give TELNET a way to find out what version this is */
98 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
100 command_print(cmd_ctx, OPENOCD_VERSION);
105 static int daemon_startup = 0;
107 int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
112 return ERROR_COMMAND_SYNTAX_ERROR;
114 daemon_startup = strcmp("reset", args[0])==0;
116 command_print(cmd_ctx, OPENOCD_VERSION);
121 void exit_handler(void)
123 /* close JTAG interface */
124 if (jtag && jtag->quit)
128 /* OpenOCD can't really handle failure of this command. Patches welcome! :-) */
129 int handle_init_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
132 static int initialized=0;
138 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
140 atexit(exit_handler);
142 if (target_init(cmd_ctx) != ERROR_OK)
144 LOG_DEBUG("target init complete");
146 if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
148 /* we must be able to set up the jtag interface */
151 LOG_DEBUG("jtag interface init complete");
153 /* Try to initialize & examine the JTAG chain at this point, but
154 * continue startup regardless */
155 if (jtag_init(cmd_ctx) == ERROR_OK)
157 LOG_DEBUG("jtag init complete");
158 if (target_examine(cmd_ctx) == ERROR_OK)
160 LOG_DEBUG("jtag examine complete");
164 if (flash_init_drivers(cmd_ctx) != ERROR_OK)
166 LOG_DEBUG("flash init complete");
168 if (nand_init(cmd_ctx) != ERROR_OK)
170 LOG_DEBUG("NAND init complete");
172 if (pld_init(cmd_ctx) != ERROR_OK)
174 LOG_DEBUG("pld init complete");
176 /* initialize tcp server */
179 /* initialize telnet subsystem */
180 telnet_init("Open On-Chip Debugger");
182 tcl_init(); /* allows tcl to just connect without going thru telnet */
188 command_context_t *active_cmd_ctx;
190 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
193 Jim_Obj *nameObjPtr, *valObjPtr;
196 namebuf = alloc_printf("%s(%d)", varname, idx);
198 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
199 valObjPtr = Jim_NewIntObj(interp, val);
200 Jim_IncrRefCount(nameObjPtr);
201 Jim_IncrRefCount(valObjPtr);
202 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
203 Jim_DecrRefCount(interp, nameObjPtr);
204 Jim_DecrRefCount(interp, valObjPtr);
206 /* printf( "%s = 0%08x\n", namebuf, val ); */
210 static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
223 /* argv[1] = name of array to receive the data
224 * argv[2] = desired width
225 * argv[3] = memory address
226 * argv[4] = length in bytes to read
229 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
232 varname = Jim_GetString(argv[1], &len);
233 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
235 e = Jim_GetLong(interp, argv[2], &l);
241 e = Jim_GetLong(interp, argv[3], &l);
246 e = Jim_GetLong(interp, argv[4], &l);
262 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
263 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
267 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
268 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
271 if ((addr + (len * width)) < addr) {
272 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
273 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
276 /* absurd transfer size? */
278 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
279 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
284 ((width == 2) && ((addr & 1) == 0)) ||
285 ((width == 4) && ((addr & 3) == 0))) {
289 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
290 sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
291 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
295 target = get_current_target(active_cmd_ctx);
304 /* Slurp... in buffer size chunks */
306 count = len; /* in objects.. */
307 if (count > (sizeof(buffer)/width)) {
308 count = (sizeof(buffer)/width);
311 retval = target->type->read_memory( target, addr, width, count, buffer );
313 if (retval != ERROR_OK) {
315 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
316 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
317 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
321 v = 0; /* shut up gcc */
322 for (i = 0 ;i < count ;i++, n++) {
325 v = target_buffer_get_u32(target, &buffer[i*width]);
328 v = target_buffer_get_u16(target, &buffer[i*width]);
331 v = buffer[i] & 0x0ff;
334 new_int_array_element(interp, varname, n, v);
340 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
345 static void tcl_output(void *privData, const char *file, int line, const char *function, const char *string)
347 Jim_Obj *tclOutput=(Jim_Obj *)privData;
349 Jim_AppendString(interp, tclOutput, string, strlen(string));
352 /* try to execute as Jim command, otherwise fall back to standard command.
353 * Note that even if the Jim command caused an error, then we succeeded
354 * to execute it, hence this fn pretty much always returns ERROR_OK. */
355 int jim_command(command_context_t *context, char *line)
358 int retcode=Jim_Eval(interp, line);
362 result = Jim_GetString(Jim_GetResult(interp), &reslen);
363 if (retcode == JIM_ERR) {
366 LOG_USER_N("Runtime error, file \"%s\", line %d:" JIM_NL, interp->errorFileName, interp->errorLine);
367 LOG_USER_N(" %s" JIM_NL,
368 Jim_GetString(interp->result, NULL));
369 Jim_ListLength(interp, interp->stackTrace, &len);
370 for (i = 0; i < len; i += 3) {
372 const char *proc, *file, *line;
374 Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
375 proc = Jim_GetString(objPtr, NULL);
376 Jim_ListIndex(interp, interp->stackTrace, i+1, &objPtr, JIM_NONE);
377 file = Jim_GetString(objPtr, NULL);
378 Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr, JIM_NONE);
379 line = Jim_GetString(objPtr, NULL);
380 LOG_USER_N("In procedure '%s' called at file \"%s\", line %s" JIM_NL, proc, file, line);
382 } else if (retcode == JIM_EXIT) {
384 /* exit(Jim_GetExitCode(interp)); */
389 for (i = 0; i < reslen; i += 256)
395 strncpy(buff, result, chunk);
397 LOG_USER_N("%s", buff);
399 LOG_USER_N("%s", "\n");
407 static int Jim_Command_openocd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int ignore)
410 char *cmd = (char*)Jim_GetString(argv[1], NULL);
412 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
416 /* We don't know whether or not the telnet/gdb server is running... */
417 target_call_timer_callbacks_now();
420 log_add_callback(tcl_output, tclOutput);
421 retval=command_run_line_internal(active_cmd_ctx, cmd);
425 target_call_timer_callbacks_now();
427 log_remove_callback(tcl_output, tclOutput);
429 Jim_SetResult(interp, tclOutput);
431 return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
434 static int Jim_Command_openocd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
436 return Jim_Command_openocd_ignore(interp, argc, argv, 1);
439 static int Jim_Command_openocd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
441 return Jim_Command_openocd_ignore(interp, argc, argv, 0);
444 /* find full path to file */
445 static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
449 char *file = (char*)Jim_GetString(argv[1], NULL);
450 char *full_path = find_file(file);
451 if (full_path == NULL)
453 Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
456 Jim_SetResult(interp, result);
460 static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
464 char *str = (char*)Jim_GetString(argv[1], NULL);
469 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
474 /* make it a char easier to read code */
482 if (!active_cmd_ctx) {
483 /* TODO: Where should this go? */
487 /* do we have to chunk it? */
488 if (ptr[nbytes] == 0) {
489 /* no it is a C style string */
490 command_output_text(active_cmd_ctx, ptr);
493 /* GRR we must chunk - not null terminated */
503 memcpy(chunk, ptr, x);
507 command_output_text(active_cmd_ctx, chunk);
515 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
517 /* TCL wants to read... tell him no */
521 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
527 if (active_cmd_ctx) {
528 cp = alloc_vprintf(fmt, ap);
530 command_output_text(active_cmd_ctx, cp);
538 static int openocd_jim_fflush(void *cookie)
540 /* nothing to flush */
544 static char* openocd_jim_fgets(char *s, int size, void *cookie)
553 Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
554 Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
555 Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
556 Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
557 Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
559 /* Set Jim's STDIO */
560 interp->cookie_stdin = NULL;
561 interp->cookie_stdout = NULL;
562 interp->cookie_stderr = NULL;
563 interp->cb_fwrite = openocd_jim_fwrite;
564 interp->cb_fread = openocd_jim_fread ;
565 interp->cb_vfprintf = openocd_jim_vfprintf;
566 interp->cb_fflush = openocd_jim_fflush;
567 interp->cb_fgets = openocd_jim_fgets;
570 /* after command line parsing */
573 Jim_Eval(interp, "source [find tcl/commands.tcl]");
576 command_context_t *setup_command_handler(void)
578 command_context_t *cmd_ctx;
580 cmd_ctx = command_init();
582 register_command(cmd_ctx, NULL, "version", handle_version_command,
583 COMMAND_EXEC, "show OpenOCD version");
584 register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG,
585 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
587 /* register subsystem commands */
588 server_register_commands(cmd_ctx);
589 telnet_register_commands(cmd_ctx);
590 gdb_register_commands(cmd_ctx);
591 tcl_register_commands(cmd_ctx); /* tcl server commands */
592 log_register_commands(cmd_ctx);
593 jtag_register_commands(cmd_ctx);
594 interpreter_register_commands(cmd_ctx);
595 xsvf_register_commands(cmd_ctx);
596 target_register_commands(cmd_ctx);
597 flash_register_commands(cmd_ctx);
598 nand_register_commands(cmd_ctx);
599 pld_register_commands(cmd_ctx);
601 if (log_init(cmd_ctx) != ERROR_OK)
605 LOG_DEBUG("log init complete");
607 LOG_OUTPUT( OPENOCD_VERSION "\n" );
610 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
611 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
612 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
613 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
614 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
615 LOG_OUTPUT( "$URL$\n");
616 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
617 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
618 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
619 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
620 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
622 register_command(cmd_ctx, NULL, "init", handle_init_command,
623 COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
628 /* normally this is the main() function entry, but if OpenOCD is linked
629 * into application, then this fn will not be invoked, but rather that
630 * application will have it's own implementation of main(). */
631 int openocd_main(int argc, char *argv[])
635 /* Create an interpreter */
636 interp = Jim_CreateInterp();
637 /* Add all the Jim core commands */
638 Jim_RegisterCoreCommands(interp);
643 /* initialize commandline interface */
644 command_context_t *cmd_ctx;
645 cmd_ctx=setup_command_handler();
647 command_context_t *cfg_cmd_ctx;
648 cfg_cmd_ctx = copy_command_context(cmd_ctx);
649 cfg_cmd_ctx->mode = COMMAND_CONFIG;
650 command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
652 active_cmd_ctx=cfg_cmd_ctx;
654 if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
659 if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
662 active_cmd_ctx=cmd_ctx;
664 command_done(cfg_cmd_ctx);
666 if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
670 command_run_line(cmd_ctx, "reset");
674 /* handle network connections */
675 server_loop(cmd_ctx);
677 /* shut server down */
680 unregister_all_commands(cmd_ctx);
682 /* free commandline interface */
683 command_done(cmd_ctx);