/** OpenOCD runtime meat that can become single-thread in future. It parse * commandline, reads configuration, sets up the target and starts server loop. * Commandline arguments are passed into this function from openocd_main(). */ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ctx) { int ret; if (parse_cmdline_args(cmd_ctx, argc, argv) != ERROR_OK) return EXIT_FAILURE; if (server_preinit() != ERROR_OK) return EXIT_FAILURE; ret = parse_config_file(cmd_ctx); if (ret != ERROR_OK) return EXIT_FAILURE; ret = server_init(cmd_ctx); if (ERROR_OK != ret) return EXIT_FAILURE; ret = command_run_line(cmd_ctx, "init_targets"); if (ERROR_OK != ret) ret = EXIT_FAILURE; if (init_at_startup) { ret = command_run_line(cmd_ctx, "init"); if (ERROR_OK != ret) return EXIT_FAILURE; } server_loop(cmd_ctx); server_quit(); return ret; }
int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]) { int c; char command_buffer[128]; while (1) { /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long(argc, argv, "hd::l:f:", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case 0: break; case 'h': /* --help | -h */ help_flag = 1; break; case 'f': /* --file | -f */ config_file_name = optarg; break; case 'd': /* --debug | -d */ if (optarg) snprintf(command_buffer, 128, "debug_level %s", optarg); else snprintf(command_buffer, 128, "debug_level 3"); command_run_line(cmd_ctx, command_buffer); break; case 'l': /* --log_output | -l */ if (optarg) { snprintf(command_buffer, 128, "log_output %s", optarg); command_run_line(cmd_ctx, command_buffer); } break; } } if (help_flag) { printf("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n"); printf("--help | -h\tdisplay this help\n"); printf("--file | -f\tuse configuration file <name>\n"); printf("--debug | -d\tset debug level <0-3>\n"); printf("--log_output | -l\tredirect log output to file <name>\n"); exit(-1); } return ERROR_OK; }
/* normally this is the main() function entry, but if OpenOCD is linked * into application, then this fn will not be invoked, but rather that * application will have it's own implementation of main(). */ int openocd_main(int argc, char *argv[]) { int ret; /* initialize commandline interface */ command_context_t *cmd_ctx; cmd_ctx = setup_command_handler(); #if BUILD_IOUTIL if (ioutil_init(cmd_ctx) != ERROR_OK) { return EXIT_FAILURE; } #endif LOG_OUTPUT("\n\nBUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS\n\n\n"); print_version(); command_context_mode(cmd_ctx, COMMAND_CONFIG); command_set_output_handler(cmd_ctx, configuration_output_handler, NULL); if (parse_cmdline_args(cmd_ctx, argc, argv) != ERROR_OK) return EXIT_FAILURE; ret = parse_config_file(cmd_ctx); if ( (ret != ERROR_OK) && (ret != ERROR_COMMAND_CLOSE_CONNECTION) ) return EXIT_FAILURE; #if BUILD_HTTPD if (httpd_start()!=ERROR_OK) return EXIT_FAILURE; #endif if (ret != ERROR_COMMAND_CLOSE_CONNECTION) { command_context_mode(cmd_ctx, COMMAND_EXEC); if (command_run_line(cmd_ctx, "init")!=ERROR_OK) return EXIT_FAILURE; /* handle network connections */ server_loop(cmd_ctx); } /* shut server down */ server_quit(); #if BUILD_HTTPD httpd_stop(); #endif unregister_all_commands(cmd_ctx); /* free commandline interface */ command_done(cmd_ctx); return EXIT_SUCCESS; }
int parse_config_file(struct command_context *cmd_ctx) { int retval; char **cfg; if (!config_file_names) { command_run_line(cmd_ctx, "script openocd.cfg"); return ERROR_OK; } cfg = config_file_names; while (*cfg) { retval = command_run_line(cmd_ctx, *cfg); if (retval != ERROR_OK) return retval; cfg++; } return ERROR_OK; }
int command_run_linef(struct command_context *context, const char *format, ...) { int retval = ERROR_FAIL; char *string; va_list ap; va_start(ap, format); string = alloc_vprintf(format, ap); if (string != NULL) { retval = command_run_line(context, string); free(string); } va_end(ap); return retval; }
/** OpenOCD runtime meat that can become single-thread in future. It parse * commandline, reads configuration, sets up the target and starts server loop. * Commandline arguments are passed into this function from openocd_main(). */ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ctx) { int ret; if (parse_cmdline_args(cmd_ctx, argc, argv) != ERROR_OK) return ERROR_FAIL; if (server_preinit() != ERROR_OK) return ERROR_FAIL; ret = parse_config_file(cmd_ctx); if (ret == ERROR_COMMAND_CLOSE_CONNECTION) return ERROR_OK; else if (ret != ERROR_OK) return ERROR_FAIL; ret = server_init(cmd_ctx); if (ERROR_OK != ret) return ERROR_FAIL; if (init_at_startup) { ret = command_run_line(cmd_ctx, "init"); if (ERROR_OK != ret) { server_quit(); return ERROR_FAIL; } } ret = server_loop(cmd_ctx); int last_signal = server_quit(); if (last_signal != ERROR_OK) return last_signal; if (ret != ERROR_OK) return ERROR_FAIL; return ERROR_OK; }
static int telnet_input(struct connection *connection) { int bytes_read; unsigned char buffer[TELNET_BUFFER_SIZE]; unsigned char *buf_p; struct telnet_connection *t_con = connection->priv; struct command_context *command_context = connection->cmd_ctx; bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE); if (bytes_read == 0) return ERROR_SERVER_REMOTE_CLOSED; else if (bytes_read == -1) { LOG_ERROR("error during read: %s", strerror(errno)); return ERROR_SERVER_REMOTE_CLOSED; } buf_p = buffer; while (bytes_read) { switch (t_con->state) { case TELNET_STATE_DATA: if (*buf_p == 0xff) t_con->state = TELNET_STATE_IAC; else { if (isprint(*buf_p)) { /* printable character */ /* watch buffer size leaving one spare character for * string null termination */ if (t_con->line_size == TELNET_LINE_MAX_SIZE-1) { /* output audible bell if buffer is full * "\a" does not work, at least on windows */ telnet_write(connection, "\x07", 1); } else if (t_con->line_cursor == t_con->line_size) { telnet_write(connection, buf_p, 1); t_con->line[t_con->line_size++] = *buf_p; t_con->line_cursor++; } else { int i; memmove(t_con->line + t_con->line_cursor + 1, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); t_con->line[t_con->line_cursor] = *buf_p; t_con->line_size++; telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); t_con->line_cursor++; for (i = t_con->line_cursor; i < t_con->line_size; i++) telnet_write(connection, "\b", 1); } } else { /* non-printable */ if (*buf_p == 0x1b) { /* escape */ t_con->state = TELNET_STATE_ESCAPE; t_con->last_escape = '\x00'; } else if ((*buf_p == 0xd) || (*buf_p == 0xa)) { /* CR/LF */ int retval; /* skip over combinations with CR/LF and NUL characters */ if ((bytes_read > 1) && ((*(buf_p + 1) == 0xa) || (*(buf_p + 1) == 0xd))) { buf_p++; bytes_read--; } if ((bytes_read > 1) && (*(buf_p + 1) == 0)) { buf_p++; bytes_read--; } t_con->line[t_con->line_size] = 0; telnet_write(connection, "\r\n\x00", 3); if (strcmp(t_con->line, "history") == 0) { int i; for (i = 1; i < TELNET_LINE_HISTORY_SIZE; i++) { /* the t_con->next_history line contains empty string * (unless NULL), thus it is not printed */ char *history_line = t_con->history[(t_con-> next_history + i) % TELNET_LINE_HISTORY_SIZE]; if (history_line) { telnet_write(connection, history_line, strlen(history_line)); telnet_write(connection, "\r\n\x00", 3); } } t_con->line_size = 0; t_con->line_cursor = 0; continue; } /* save only non-blank not repeating lines in the history */ char *prev_line = t_con->history[(t_con->current_history > 0) ? t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1]; if (*t_con->line && (prev_line == NULL || strcmp(t_con->line, prev_line))) { /* if the history slot is already taken, free it */ if (t_con->history[t_con->next_history]) free(t_con->history[t_con->next_history]); /* add line to history */ t_con->history[t_con->next_history] = strdup(t_con->line); /* wrap history at TELNET_LINE_HISTORY_SIZE */ t_con->next_history = (t_con->next_history + 1) % TELNET_LINE_HISTORY_SIZE; /* current history line starts at the new entry */ t_con->current_history = t_con->next_history; if (t_con->history[t_con->current_history]) free(t_con->history[t_con->current_history]); t_con->history[t_con->current_history] = strdup(""); } t_con->line_size = 0; /* to suppress prompt in log callback during command execution */ t_con->line_cursor = -1; if (strcmp(t_con->line, "shutdown") == 0) telnet_save_history(t_con); retval = command_run_line(command_context, t_con->line); t_con->line_cursor = 0; if (retval == ERROR_COMMAND_CLOSE_CONNECTION) return ERROR_SERVER_REMOTE_CLOSED; /* the prompt is always * placed at the line beginning */ telnet_write(connection, "\r", 1); retval = telnet_prompt(connection); if (retval == ERROR_SERVER_REMOTE_CLOSED) return ERROR_SERVER_REMOTE_CLOSED; } else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) { /* delete character */ if (t_con->line_cursor > 0) { if (t_con->line_cursor != t_con->line_size) { int i; telnet_write(connection, "\b", 1); t_con->line_cursor--; t_con->line_size--; memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor); telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); telnet_write(connection, " \b", 2); for (i = t_con->line_cursor; i < t_con->line_size; i++) telnet_write(connection, "\b", 1); } else { t_con->line_size--; t_con->line_cursor--; /* back space: move the 'printer' head one char * back, overwrite with space, move back again */ telnet_write(connection, "\b \b", 3); } } } else if (*buf_p == 0x15) /* clear line */ telnet_clear_line(connection, t_con); else if (*buf_p == CTRL('B')) { /* cursor left */ if (t_con->line_cursor > 0) { telnet_write(connection, "\b", 1); t_con->line_cursor--; } t_con->state = TELNET_STATE_DATA; } else if (*buf_p == CTRL('F')) { /* cursor right */ if (t_con->line_cursor < t_con->line_size) telnet_write(connection, t_con->line + t_con->line_cursor++, 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == CTRL('P')) /* cursor up */ telnet_history_up(connection); else if (*buf_p == CTRL('N')) /* cursor down */ telnet_history_down(connection); else LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p); } } break; case TELNET_STATE_IAC: switch (*buf_p) { case 0xfe: t_con->state = TELNET_STATE_DONT; break; case 0xfd: t_con->state = TELNET_STATE_DO; break; case 0xfc: t_con->state = TELNET_STATE_WONT; break; case 0xfb: t_con->state = TELNET_STATE_WILL; break; } break; case TELNET_STATE_SB: break; case TELNET_STATE_SE: break; case TELNET_STATE_WILL: case TELNET_STATE_WONT: case TELNET_STATE_DO: case TELNET_STATE_DONT: t_con->state = TELNET_STATE_DATA; break; case TELNET_STATE_ESCAPE: if (t_con->last_escape == '[') { if (*buf_p == 'D') { /* cursor left */ if (t_con->line_cursor > 0) { telnet_write(connection, "\b", 1); t_con->line_cursor--; } t_con->state = TELNET_STATE_DATA; } else if (*buf_p == 'C') { /* cursor right */ if (t_con->line_cursor < t_con->line_size) telnet_write(connection, t_con->line + t_con->line_cursor++, 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == 'A') { /* cursor up */ telnet_history_up(connection); } else if (*buf_p == 'B') { /* cursor down */ telnet_history_down(connection); } else if (*buf_p == '3') t_con->last_escape = *buf_p; else t_con->state = TELNET_STATE_DATA; } else if (t_con->last_escape == '3') { /* Remove character */ if (*buf_p == '~') { if (t_con->line_cursor < t_con->line_size) { int i; t_con->line_size--; /* remove char from line buffer */ memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor); /* print remainder of buffer */ telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor); /* overwrite last char with whitespace */ telnet_write(connection, " \b", 2); /* move back to cursor position*/ for (i = t_con->line_cursor; i < t_con->line_size; i++) telnet_write(connection, "\b", 1); } t_con->state = TELNET_STATE_DATA; } else t_con->state = TELNET_STATE_DATA; } else if (t_con->last_escape == '\x00') { if (*buf_p == '[') t_con->last_escape = *buf_p; else t_con->state = TELNET_STATE_DATA; } else { LOG_ERROR("BUG: unexpected value in t_con->last_escape"); t_con->state = TELNET_STATE_DATA; } break; default: LOG_ERROR("unknown telnet state"); return ERROR_FAIL; } bytes_read--; buf_p++; } return ERROR_OK; }
int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]) { int c; char command_buffer[128]; while (1) { /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case 0: break; case 'h': /* --help | -h */ help_flag = 1; break; case 'v': /* --version | -v */ version_flag = 1; break; case 'f': /* --file | -f */ { snprintf(command_buffer, 128, "script {%s}", optarg); add_config_command(command_buffer); break; } case 's': /* --search | -s */ add_script_search_dir(optarg); break; case 'd': /* --debug | -d */ if (optarg) snprintf(command_buffer, 128, "debug_level %s", optarg); else snprintf(command_buffer, 128, "debug_level 3"); command_run_line(cmd_ctx, command_buffer); break; case 'l': /* --log_output | -l */ if (optarg) { snprintf(command_buffer, 128, "log_output %s", optarg); command_run_line(cmd_ctx, command_buffer); } break; case 'c': /* --command | -c */ if (optarg) { add_config_command(optarg); } break; case 'p': /* --pipe | -p */ #if BUILD_ECOSBOARD == 1 /* pipes unsupported on hosted platforms */ LOG_WARNING("pipes not supported on this platform"); #else server_use_pipes = 1; #endif break; } } if (help_flag) { LOG_OUTPUT("Open On-Chip Debugger\n(c) 2005-2008 by Dominic Rath\n\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n"); LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--file | -f\tuse configuration file <name>\n"); LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n"); LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n"); LOG_OUTPUT("--command | -c\trun <command>\n"); LOG_OUTPUT("--pipe | -p\tuse pipes for gdb communication\n"); exit(-1); } if (version_flag) { /* Nothing to do, version gets printed automatically. */ // It is not an error to request the VERSION number. exit(0); } return ERROR_OK; }
int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) { int c; char command_buffer[128]; while (1) { /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case 0: break; case 'h': /* --help | -h */ help_flag = 1; break; case 'v': /* --version | -v */ version_flag = 1; break; case 'f': /* --file | -f */ { snprintf(command_buffer, 128, "script {%s}", optarg); add_config_command(command_buffer); break; } case 's': /* --search | -s */ add_script_search_dir(optarg); break; case 'd': /* --debug | -d */ if (optarg) snprintf(command_buffer, 128, "debug_level %s", optarg); else snprintf(command_buffer, 128, "debug_level 3"); command_run_line(cmd_ctx, command_buffer); break; case 'l': /* --log_output | -l */ if (optarg) { snprintf(command_buffer, 128, "log_output %s", optarg); command_run_line(cmd_ctx, command_buffer); } break; case 'c': /* --command | -c */ if (optarg) add_config_command(optarg); break; case 'p': /* to replicate the old syntax this needs to be synchronous * otherwise the gdb stdin will overflow with the warning message */ command_run_line(cmd_ctx, "gdb_port pipe; log_output openocd.log"); LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; " "log_output openocd.log\"' instead."); break; } } if (help_flag) { LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n"); LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--file | -f\tuse configuration file <name>\n"); LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n"); LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n"); LOG_OUTPUT("--command | -c\trun <command>\n"); exit(-1); } if (version_flag) { /* Nothing to do, version gets printed automatically. */ /* It is not an error to request the VERSION number. */ exit(0); } /* paths specified on the command line take precedence over these * built-in paths */ add_default_dirs(); return ERROR_OK; }
/* call routine */ int fn_call(void *pvHandle, unsigned long ulNetxAddress, unsigned long ulParameterR0, lua_State *L, int iLuaCallbackTag, void *pvCallbackUserData) { command_context_t *cmd_ctx; int iOocdResult; int iResult; wxString strCmd; target_t *target; bool fIsRunning; enum target_state state; /* cast the handle to the command context */ cmd_ctx = (command_context_t*)pvHandle; // expect failure iResult = 1; // set R0 parameter strCmd.Printf(wxT("reg r0 0x%08X"), ulParameterR0); iOocdResult = command_run_line(cmd_ctx, strCmd.ToAscii()); if( iOocdResult!=ERROR_OK ) { wxLogError(wxT("config failed!")); } else { // resume <ulNetxAddress> strCmd.Printf(wxT("resume 0x%08X"), ulNetxAddress); iOocdResult = command_run_line(cmd_ctx, strCmd.ToAscii()); if( iOocdResult!=ERROR_OK ) { wxLogError(wxT("config failed!")); } else { // grab messages here // TODO: redirect outputhandler, then grab messages, restore default output handler on halt // wait for halt target = get_current_target(cmd_ctx); do { wxMilliSleep(100); target->type->poll(target); state = target->state; if( state==TARGET_HALTED ) { wxLogMessage(wxT("call finished!")); iResult = 0; } else { // execute callback fIsRunning = callback(L, iLuaCallbackTag, 0, pvCallbackUserData); if( fIsRunning!=true ) { // operation was canceled, halt the target wxLogMessage(wxT("Call canceled, stopping target...")); target = get_current_target(cmd_ctx); iOocdResult = target->type->halt(target); if( iOocdResult!=ERROR_OK && iOocdResult!=ERROR_TARGET_ALREADY_HALTED ) { wxLogError(wxT("Failed to halt target!")); } break; } else { target_call_timer_callbacks(); } } } while( state!=TARGET_HALTED ); // usb cmd delay wxMilliSleep(1); } } return iResult; }
static int romloader_openocd_connect(command_context_t **pptCmdCtx) { int iResult; command_context_t *cmd_ctx; target_t *target; wxString strCmd; wxString strMsg; size_t sizCfgCnt; size_t sizCfgMax; int iInitCnt; cmd_ctx = command_init(); /* register subsystem commands */ log_register_commands(cmd_ctx); jtag_register_commands(cmd_ctx); interpreter_register_commands(cmd_ctx); xsvf_register_commands(cmd_ctx); target_register_commands(cmd_ctx); /* init the log functions */ iResult = log_init(cmd_ctx); if( iResult!=ERROR_OK ) { strMsg.Printf(wxT("failed to init log level: %d"), iResult); wxLogError(strMsg); } else { command_set_output_handler(cmd_ctx, romloader_openocd_default_output_handler, NULL); log_set_output_handler(romloader_openocd_log_printf, romloader_openocd_short_log_printf); cmd_ctx->mode = COMMAND_CONFIG; // set config sizCfgCnt = 0; sizCfgMax = astrInitCfg.GetCount(); while( sizCfgCnt<sizCfgMax ) { strCmd = astrInitCfg.Item(sizCfgCnt); wxLogMessage(wxT("command: ") + strCmd); iResult = command_run_line(cmd_ctx, strCmd.ToAscii()); if( iResult!=ERROR_OK ) { strMsg.Printf(wxT("failed to set config: %d"), iResult); wxLogError(strMsg); strMsg = wxT("error line was: '") + strCmd + wxT("'"); wxLogError(strMsg); break; } ++sizCfgCnt; } if( iResult==ERROR_OK ) { cmd_ctx->mode = COMMAND_EXEC; iResult = jtag_init(cmd_ctx); if( iResult!=ERROR_OK ) { strMsg.Printf(wxT("failed to init jtag: %d"), iResult); wxLogError(strMsg); } else { iResult = target_init(cmd_ctx); if( iResult!=ERROR_OK ) { strMsg.Printf(wxT("failed to init jtag: %d"), iResult); wxLogError(strMsg); } else { wxMilliSleep(500); /* wait for target reset */ iInitCnt = 10; do { target_call_timer_callbacks(); wxMilliSleep(100); } while( --iInitCnt>0 ); target = get_current_target(cmd_ctx); if( target->state!=TARGET_HALTED ) { wxLogError(wxT("failed to halt the target")); iResult = ERROR_TARGET_NOT_HALTED; } else { // set config sizCfgCnt = 0; sizCfgMax = astrRunCfg.GetCount(); while( sizCfgCnt<sizCfgMax ) { strCmd = astrRunCfg.Item(sizCfgCnt); wxLogMessage(wxT("command: ") + strCmd); iResult = command_run_line(cmd_ctx, strCmd.ToAscii()); if( iResult!=ERROR_OK ) { strMsg.Printf(wxT("failed to run command: %d"), iResult); wxLogError(strMsg); strMsg = wxT("error line was: '") + strCmd + wxT("'"); wxLogError(strMsg); break; } ++sizCfgCnt; } if( iResult!=ERROR_OK ) { wxLogError(wxT("config failed!")); } } } } } } if( iResult!=ERROR_OK ) { // close connection romloader_openocd_close_instance(cmd_ctx); *pptCmdCtx = NULL; } else { // connection open, ok! *pptCmdCtx = cmd_ctx; } return iResult; }