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");
151 /* implementations of OpenOCD that uses multithreading needs to lock OpenOCD while calling
152 * OpenOCD fn's. No-op in vanilla OpenOCD
166 command_context_t *active_cmd_ctx;
168 static void tcl_output(void *privData, const char *file, int line,
169 const char *function, const char *string)
171 Jim_Obj *tclOutput=(Jim_Obj *)privData;
173 Jim_AppendString(interp, tclOutput, string, strlen(string));
176 /* try to execute as Jim command, otherwise fall back to standard command.
178 Note that even if the Jim command caused an error, then we succeeded
179 to execute it, hence this fn pretty much always returns ERROR_OK.
182 int jim_command(command_context_t *context, char *line)
185 /* FIX!!!! in reality there is only one cmd_ctx handler, but consider
186 what might happen here if there are multiple handlers w/reentrant callback
188 active_cmd_ctx=context;
189 int retcode=Jim_Eval(interp, line);
193 result = Jim_GetString(Jim_GetResult(interp), &reslen);
194 if (retcode == JIM_ERR) {
197 LOG_USER_N("Runtime error, file \"%s\", line %d:" JIM_NL,
198 interp->errorFileName, interp->errorLine);
199 LOG_USER_N(" %s" JIM_NL,
200 Jim_GetString(interp->result, NULL));
201 Jim_ListLength(interp, interp->stackTrace, &len);
202 for (i = 0; i < len; i+= 3) {
204 const char *proc, *file, *line;
206 Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
207 proc = Jim_GetString(objPtr, NULL);
208 Jim_ListIndex(interp, interp->stackTrace, i+1, &objPtr,
210 file = Jim_GetString(objPtr, NULL);
211 Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr,
213 line = Jim_GetString(objPtr, NULL);
214 LOG_USER_N("In procedure '%s' called at file \"%s\", line %s" JIM_NL,
217 } else if (retcode == JIM_EXIT) {
219 //exit(Jim_GetExitCode(interp));
224 for (i=0; i<reslen; i+=256)
230 strncpy(buff, result, chunk);
232 LOG_USER_N("%s", buff);
234 LOG_USER_N("%s", "\n");
240 static int startLoop=0;
243 Jim_Command_openocd_ignore(Jim_Interp *interp,
245 Jim_Obj *const *argv,
249 char *cmd = (char*)Jim_GetString(argv[1], NULL);
253 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
257 // We don't know whether or not the telnet/gdb server is running...
258 target_call_timer_callbacks_now();
261 log_add_callback(tcl_output, tclOutput);
262 retval=command_run_line_internal(active_cmd_ctx, cmd);
266 target_call_timer_callbacks_now();
268 log_remove_callback(tcl_output, tclOutput);
270 Jim_SetResult(interp, tclOutput);
273 return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
277 Jim_Command_openocd(Jim_Interp *interp,
279 Jim_Obj *const *argv)
281 return Jim_Command_openocd_ignore(interp, argc, argv, 1);
285 Jim_Command_openocd_throw(Jim_Interp *interp,
287 Jim_Obj *const *argv)
289 return Jim_Command_openocd_ignore(interp, argc, argv, 0);
295 /* find full path to file */
297 Jim_Command_find(Jim_Interp *interp,
299 Jim_Obj *const *argv)
303 char *file = (char*)Jim_GetString(argv[1], NULL);
304 char *full_path=find_file(file);
307 Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
310 Jim_SetResult(interp, result);
315 Jim_Command_echo(Jim_Interp *interp,
317 Jim_Obj *const *argv)
321 char *str = (char*)Jim_GetString(argv[1], NULL);
330 /* Create an interpreter */
331 interp = Jim_CreateInterp();
332 /* Add all the Jim core commands */
333 Jim_RegisterCoreCommands(interp);
334 Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
335 Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
336 Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
337 Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
340 int main(int argc, char *argv[])
344 /* initialize commandline interface */
345 command_context_t *cmd_ctx, *cfg_cmd_ctx;
346 cmd_ctx = command_init();
348 register_command(cmd_ctx, NULL, "version", handle_version_command,
349 COMMAND_EXEC, "show OpenOCD version");
350 register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG,
351 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
353 /* register subsystem commands */
354 server_register_commands(cmd_ctx);
355 telnet_register_commands(cmd_ctx);
356 gdb_register_commands(cmd_ctx);
357 log_register_commands(cmd_ctx);
358 jtag_register_commands(cmd_ctx);
359 interpreter_register_commands(cmd_ctx);
360 xsvf_register_commands(cmd_ctx);
361 target_register_commands(cmd_ctx);
362 flash_register_commands(cmd_ctx);
363 nand_register_commands(cmd_ctx);
364 pld_register_commands(cmd_ctx);
366 if (log_init(cmd_ctx) != ERROR_OK)
368 LOG_DEBUG("log init complete");
370 LOG_OUTPUT( OPENOCD_VERSION "\n" );
373 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
374 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
375 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
376 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
377 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
378 LOG_OUTPUT( "$URL$\n");
379 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
380 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
381 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
382 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
383 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
385 register_command(cmd_ctx, NULL, "init", handle_init_command,
386 COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
388 cfg_cmd_ctx = copy_command_context(cmd_ctx);
389 cfg_cmd_ctx->mode = COMMAND_CONFIG;
390 command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
392 if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
395 Jim_Eval(interp, "source [find tcl/commands.tcl]");
397 if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
400 command_done(cfg_cmd_ctx);
402 if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
406 command_run_line(cmd_ctx, "reset");
411 /* handle network connections */
412 server_loop(cmd_ctx);
414 /* shut server down */
417 unregister_all_commands(cmd_ctx);
419 /* free commandline interface */
420 command_done(cmd_ctx);