- fixed build issues with win32
[openocd.git] / src / openocd.c
blobee00f19adb2e7b67c94eefaef74192e5476fef74
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
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. *
9 * *
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. *
14 * *
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
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include "log.h"
28 #include "types.h"
29 #include "jtag.h"
30 #include "configuration.h"
31 #include "interpreter.h"
32 #include "xsvf.h"
33 #include "target.h"
34 #include "flash.h"
35 #include "nand.h"
36 #include "pld.h"
38 #include "command.h"
39 #include "server.h"
40 #include "telnet_server.h"
41 #include "gdb_server.h"
42 #include "tcl_server.h"
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <strings.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <errno.h>
53 #ifdef _WIN32
54 #include <malloc.h>
55 #else
56 #include <alloca.h>
57 #endif
59 #ifdef __ECOS
60 /* Jim is provied by eCos */
61 #include <cyg/jimtcl/jim.h>
62 #else
63 #define JIM_EMBEDDED
64 #include "jim.h"
65 #endif
67 #include "replacements.h"
69 int launchTarget(struct command_context_s *cmd_ctx)
71 int retval;
72 /* Try to examine & validate jtag chain, though this may require a reset first
73 * in which case we continue setup */
74 jtag_init(cmd_ctx);
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);
81 if (retval!=ERROR_OK)
82 return retval;
83 LOG_DEBUG("flash init complete");
85 retval=nand_init(cmd_ctx);
86 if (retval!=ERROR_OK)
87 return retval;
88 LOG_DEBUG("NAND init complete");
90 retval=pld_init(cmd_ctx);
91 if (retval!=ERROR_OK)
92 return retval;
93 LOG_DEBUG("pld init complete");
94 return retval;
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);
102 return ERROR_OK;
105 static int daemon_startup = 0;
107 int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
109 if (argc==0)
110 return ERROR_OK;
111 if (argc > 1 )
112 return ERROR_COMMAND_SYNTAX_ERROR;
114 daemon_startup = strcmp("reset", args[0])==0;
116 command_print(cmd_ctx, OPENOCD_VERSION);
118 return ERROR_OK;
121 void exit_handler(void)
123 /* close JTAG interface */
124 if (jtag && jtag->quit)
125 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)
131 int retval;
132 static int initialized=0;
133 if (initialized)
134 return ERROR_OK;
136 initialized=1;
138 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
140 atexit(exit_handler);
142 if (target_init(cmd_ctx) != ERROR_OK)
143 return ERROR_FAIL;
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 */
149 return retval;
151 LOG_DEBUG("jtag interface init complete");
153 /* Try to initialize & examine the JTAG chain at this point, but
154 * continue startup regardless
156 if (jtag_init(cmd_ctx) == ERROR_OK)
158 LOG_DEBUG("jtag init complete");
159 if (target_examine(cmd_ctx) == ERROR_OK)
161 LOG_DEBUG("jtag examine complete");
165 if (flash_init_drivers(cmd_ctx) != ERROR_OK)
166 return ERROR_FAIL;
167 LOG_DEBUG("flash init complete");
169 if (nand_init(cmd_ctx) != ERROR_OK)
170 return ERROR_FAIL;
171 LOG_DEBUG("NAND init complete");
173 if (pld_init(cmd_ctx) != ERROR_OK)
174 return ERROR_FAIL;
175 LOG_DEBUG("pld init complete");
177 /* initialize tcp server */
178 server_init();
180 /* initialize telnet subsystem */
181 telnet_init("Open On-Chip Debugger");
182 gdb_init();
183 tcl_init(); /* allows tcl to just connect without going thru telnet */
185 return ERROR_OK;
188 void lockBigLock();
189 void unlockBigLock();
191 Jim_Interp *interp;
192 command_context_t *active_cmd_ctx;
194 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
196 char *namebuf;
197 Jim_Obj *nameObjPtr, *valObjPtr;
198 int result;
200 namebuf = alloc_printf("%s(%d)", varname, idx );
202 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
203 valObjPtr = Jim_NewIntObj(interp, val );
204 Jim_IncrRefCount(nameObjPtr);
205 Jim_IncrRefCount(valObjPtr);
206 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
207 Jim_DecrRefCount(interp, nameObjPtr);
208 Jim_DecrRefCount(interp, valObjPtr);
209 free(namebuf);
210 // printf( "%s = 0%08x\n", namebuf, val );
211 return result;
214 static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
216 target_t *target;
217 long l;
218 u32 width;
219 u32 len;
220 u32 addr;
221 u32 count;
222 u32 v;
223 const char *varname;
224 u8 buffer[4096];
225 int i,n,e,retval;
227 /* argv[1] = name of array to receive the data
228 * argv[2] = desired width
229 * argv[3] = memory address
230 * argv[4] = length in bytes to read
232 if( argc != 5 ){
233 Jim_WrongNumArgs( interp, 1, argv, "varname width addr nelems" );
234 return JIM_ERR;
236 varname = Jim_GetString( argv[1], &len );
237 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
239 e = Jim_GetLong( interp, argv[2], &l );
240 width = l;
241 if( e != JIM_OK ){
242 return e;
245 e = Jim_GetLong( interp, argv[3], &l );
246 addr = l;
247 if( e != JIM_OK ){
248 return e;
250 e = Jim_GetLong( interp, argv[4], &l );
251 len = l;
252 if( e != JIM_OK ){
253 return e;
255 switch(width){
256 case 8:
257 width = 1;
258 break;
259 case 16:
260 width = 2;
261 break;
262 case 32:
263 width = 4;
264 break;
265 default:
266 Jim_SetResult(interp,
267 Jim_NewEmptyStringObj(interp));
268 Jim_AppendStrings( interp, Jim_GetResult(interp),
269 "Invalid width param, must be 8/16/32", NULL );
270 return JIM_ERR;
272 if( len == 0 ){
273 Jim_SetResult(interp,
274 Jim_NewEmptyStringObj(interp));
275 Jim_AppendStrings( interp, Jim_GetResult(interp),
276 "mem2array: zero width read?", NULL );
277 return JIM_ERR;
279 if( (addr + (len * width)) < addr ){
280 Jim_SetResult(interp,
281 Jim_NewEmptyStringObj(interp));
282 Jim_AppendStrings( interp, Jim_GetResult(interp),
283 "mem2array: addr + len - wraps to zero?", NULL );
284 return JIM_ERR;
286 /* absurd transfer size? */
287 if( len > 65536 ){
288 Jim_SetResult(interp,
289 Jim_NewEmptyStringObj(interp));
290 Jim_AppendStrings( interp, Jim_GetResult(interp),
291 "mem2array: absurd > 64K item request", NULL );
292 return JIM_ERR;
295 if( (width == 1) ||
296 ((width == 2) && ((addr & 1) == 0)) ||
297 ((width == 4) && ((addr & 3) == 0)) ){
298 /* all is well */
299 } else {
300 char buf[100];
301 Jim_SetResult(interp,
302 Jim_NewEmptyStringObj(interp));
303 sprintf( buf,
304 "mem2array address: 0x%08x is not aligned for %d byte reads",
305 addr, width );
307 Jim_AppendStrings( interp, Jim_GetResult(interp),
308 buf , NULL );
309 return JIM_ERR;
312 target = get_current_target( active_cmd_ctx );
314 /* Transfer loop */
316 /* index counter */
317 n = 0;
318 /* assume ok */
319 e = JIM_OK;
320 while( len ){
322 /* Slurp... in buffer size chunks */
324 count = len; /* in objects.. */
325 if( count > (sizeof(buffer)/width)){
326 count = (sizeof(buffer)/width);
329 retval = target->type->read_memory( target,
330 addr,
331 width,
332 count,
333 buffer );
335 if( retval != ERROR_OK ){
336 /* BOO !*/
337 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed",
338 addr, width, count );
339 Jim_SetResult(interp,
340 Jim_NewEmptyStringObj(interp));
341 Jim_AppendStrings( interp, Jim_GetResult(interp),
342 "mem2array: cannot read memory", NULL );
343 e = JIM_ERR;
344 len = 0;
345 } else {
346 v = 0; /* shut up gcc */
347 for( i = 0 ; i < count ; i++, n++ ){
348 switch(width){
349 case 4:
350 v = target_buffer_get_u32( target, &buffer[i*width] );
351 break;
352 case 2:
353 v = target_buffer_get_u16( target, &buffer[i*width] );
354 break;
355 case 1:
356 v = buffer[i] & 0x0ff;
357 break;
359 new_int_array_element( interp, varname, n, v );
361 len -= count;
364 Jim_SetResult(interp,
365 Jim_NewEmptyStringObj(interp));
367 return JIM_OK;
370 static void tcl_output(void *privData, const char *file, int line, const char *function, const char *string)
372 Jim_Obj *tclOutput=(Jim_Obj *)privData;
374 Jim_AppendString(interp, tclOutput, string, strlen(string));
377 /* try to execute as Jim command, otherwise fall back to standard command.
379 Note that even if the Jim command caused an error, then we succeeded
380 to execute it, hence this fn pretty much always returns ERROR_OK.
383 int jim_command(command_context_t *context, char *line)
385 int retval=ERROR_OK;
386 /* FIX!!!! in reality there is only one cmd_ctx handler, but consider
387 what might happen here if there are multiple handlers w/reentrant callback
388 fn's... shudder! */
389 active_cmd_ctx=context;
390 int retcode=Jim_Eval(interp, line);
392 const char *result;
393 int reslen;
394 result = Jim_GetString(Jim_GetResult(interp), &reslen);
395 if (retcode == JIM_ERR) {
396 int len, i;
398 LOG_USER_N("Runtime error, file \"%s\", line %d:" JIM_NL,
399 interp->errorFileName, interp->errorLine);
400 LOG_USER_N(" %s" JIM_NL,
401 Jim_GetString(interp->result, NULL));
402 Jim_ListLength(interp, interp->stackTrace, &len);
403 for (i = 0; i < len; i+= 3) {
404 Jim_Obj *objPtr;
405 const char *proc, *file, *line;
407 Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
408 proc = Jim_GetString(objPtr, NULL);
409 Jim_ListIndex(interp, interp->stackTrace, i+1, &objPtr,
410 JIM_NONE);
411 file = Jim_GetString(objPtr, NULL);
412 Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr,
413 JIM_NONE);
414 line = Jim_GetString(objPtr, NULL);
415 LOG_USER_N("In procedure '%s' called at file \"%s\", line %s" JIM_NL,
416 proc, file, line);
418 } else if (retcode == JIM_EXIT) {
419 // ignore.
420 //exit(Jim_GetExitCode(interp));
421 } else {
422 if (reslen) {
423 int i;
424 char buff[256+1];
425 for (i=0; i<reslen; i+=256)
427 int chunk;
428 chunk=reslen-i;
429 if (chunk>256)
430 chunk=256;
431 strncpy(buff, result, chunk);
432 buff[chunk]=0;
433 LOG_USER_N("%s", buff);
435 LOG_USER_N("%s", "\n");
438 return retval;
441 int startLoop=0;
443 static int Jim_Command_openocd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int ignore)
445 int retval;
446 char *cmd = (char*)Jim_GetString(argv[1], NULL);
448 lockBigLock();
450 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
452 if (startLoop)
454 // We don't know whether or not the telnet/gdb server is running...
455 target_call_timer_callbacks_now();
458 log_add_callback(tcl_output, tclOutput);
459 retval=command_run_line_internal(active_cmd_ctx, cmd);
461 if (startLoop)
463 target_call_timer_callbacks_now();
465 log_remove_callback(tcl_output, tclOutput);
467 Jim_SetResult(interp, tclOutput);
468 unlockBigLock();
470 return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
473 static int Jim_Command_openocd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
475 return Jim_Command_openocd_ignore(interp, argc, argv, 1);
478 static int Jim_Command_openocd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
480 return Jim_Command_openocd_ignore(interp, argc, argv, 0);
483 /* find full path to file */
484 static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
486 if (argc!=2)
487 return JIM_ERR;
488 char *file = (char*)Jim_GetString(argv[1], NULL);
489 char *full_path=find_file(file);
490 if (full_path==NULL)
491 return JIM_ERR;
492 Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
493 free(full_path);
495 Jim_SetResult(interp, result);
496 return JIM_OK;
499 static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
501 if (argc!=2)
502 return JIM_ERR;
503 char *str = (char*)Jim_GetString(argv[1], NULL);
504 LOG_USER("%s", str);
505 return JIM_OK;
508 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
510 size_t nbytes;
511 const char *ptr;
513 /* make it a char easier to read code */
514 ptr = _ptr;
516 nbytes = size * n;
517 if( nbytes == 0 ){
518 return 0;
521 if( !active_cmd_ctx ){
522 /* FIXME: Where should this go? */
523 return n;
526 /* do we have to chunk it? */
527 if( ptr[ nbytes ] == 0 ){
528 /* no it is a C style string */
529 command_output_text( active_cmd_ctx, ptr );
530 return strlen(ptr);
532 /* GRR we must chunk - not null terminated */
533 while( nbytes ){
534 char chunk[128+1];
535 int x;
537 x = nbytes;
538 if( x > 128 ){
539 x = 128;
541 /* copy it */
542 memcpy( chunk, ptr, x );
543 /* terminate it */
544 chunk[n] = 0;
545 /* output it */
546 command_output_text( active_cmd_ctx, chunk );
547 ptr += x;
548 nbytes -= x;
551 return n;
554 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
556 /* TCL wants to read... tell him no */
557 return 0;
560 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
562 char *cp;
563 int n;
565 n = -1;
566 if( active_cmd_ctx ){
567 cp = alloc_vprintf( fmt, ap );
568 if( cp ){
569 command_output_text( active_cmd_ctx, cp );
570 n = strlen(cp);
571 free(cp);
574 return n;
577 static int openocd_jim_fflush(void *cookie)
579 /* nothing to flush */
580 return 0;
583 static char* openocd_jim_fgets(char *s, int size, void *cookie)
585 /* not supported */
586 errno = ENOTSUP;
587 return NULL;
590 void initJim(void)
592 Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
593 Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
594 Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
595 Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
596 Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
598 /* Set Jim's STDIO */
599 interp->cookie_stdin = NULL;
600 interp->cookie_stdout = NULL;
601 interp->cookie_stderr = NULL;
602 interp->cb_fwrite = openocd_jim_fwrite;
603 interp->cb_fread = openocd_jim_fread ;
604 interp->cb_vfprintf = openocd_jim_vfprintf;
605 interp->cb_fflush = openocd_jim_fflush;
606 interp->cb_fgets = openocd_jim_fgets;
609 /* after command line parsing */
610 void initJim2(void)
612 Jim_Eval(interp, "source [find tcl/commands.tcl]");
615 command_context_t *setup_command_handler()
617 command_context_t *cmd_ctx;
619 cmd_ctx = command_init();
621 register_command(cmd_ctx, NULL, "version", handle_version_command,
622 COMMAND_EXEC, "show OpenOCD version");
623 register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG,
624 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
626 /* register subsystem commands */
627 server_register_commands(cmd_ctx);
628 telnet_register_commands(cmd_ctx);
629 gdb_register_commands(cmd_ctx);
630 tcl_register_commands(cmd_ctx); /* tcl server commands */
631 log_register_commands(cmd_ctx);
632 jtag_register_commands(cmd_ctx);
633 interpreter_register_commands(cmd_ctx);
634 xsvf_register_commands(cmd_ctx);
635 target_register_commands(cmd_ctx);
636 flash_register_commands(cmd_ctx);
637 nand_register_commands(cmd_ctx);
638 pld_register_commands(cmd_ctx);
640 if (log_init(cmd_ctx) != ERROR_OK)
642 exit(-1);
644 LOG_DEBUG("log init complete");
646 LOG_OUTPUT( OPENOCD_VERSION "\n" );
649 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
650 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
651 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
652 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
653 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
654 LOG_OUTPUT( "$URL$\n");
655 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
656 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
657 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
658 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
659 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
661 register_command(cmd_ctx, NULL, "init", handle_init_command,
662 COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
664 return cmd_ctx;
668 normally this is the main() function entry, but if OpenOCD is linked
669 into application, then this fn will not be invoked, but rather that
670 application will have it's own implementation of main().
672 int openocd_main(int argc, char *argv[])
674 #ifdef JIM_EMBEDDED
675 Jim_InitEmbedded();
676 /* Create an interpreter */
677 interp = Jim_CreateInterp();
678 /* Add all the Jim core commands */
679 Jim_RegisterCoreCommands(interp);
680 #endif
682 initJim();
684 /* initialize commandline interface */
685 command_context_t *cmd_ctx;
686 cmd_ctx=setup_command_handler();
688 command_context_t *cfg_cmd_ctx;
689 cfg_cmd_ctx = copy_command_context(cmd_ctx);
690 cfg_cmd_ctx->mode = COMMAND_CONFIG;
691 command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
693 if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
694 return EXIT_FAILURE;
696 initJim2();
698 if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
699 return EXIT_FAILURE;
701 command_done(cfg_cmd_ctx);
703 if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
704 return EXIT_FAILURE;
706 if (daemon_startup)
707 command_run_line(cmd_ctx, "reset");
709 startLoop=1;
711 /* handle network connections */
712 server_loop(cmd_ctx);
714 /* shut server down */
715 server_quit();
717 unregister_all_commands(cmd_ctx);
719 /* free commandline interface */
720 command_done(cmd_ctx);
722 return EXIT_SUCCESS;