do not print jim tcl error message trace for ERROR_COMMAND_CLOSE_CONNECTION
[fw/openocd] / src / openocd.c
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  ***************************************************************************/
20
21 #define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "log.h"
28 #include "types.h"
29 #include "jtag.h"
30 #include "configuration.h"
31 #include "xsvf.h"
32 #include "target.h"
33 #include "flash.h"
34 #include "nand.h"
35 #include "pld.h"
36
37 #include "command.h"
38 #include "server.h"
39 #include "telnet_server.h"
40 #include "gdb_server.h"
41 #include "tcl_server.h"
42
43 #include <sys/time.h>
44 #include <sys/types.h>
45 #include <strings.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <errno.h>
51
52 #ifdef _WIN32
53 #include <malloc.h>
54 #else
55 #include <alloca.h>
56 #endif
57
58 #ifdef __ECOS
59 /* Jim is provied by eCos */
60 #include <cyg/jimtcl/jim.h>
61 #else
62 #define JIM_EMBEDDED
63 #include "jim.h"
64 #endif
65
66 #include "replacements.h"
67
68
69 /* Give TELNET a way to find out what version this is */
70 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
71 {
72         command_print(cmd_ctx, OPENOCD_VERSION);
73
74         return ERROR_OK;
75 }
76
77 static int daemon_startup = 0;
78
79 int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
80 {
81         if (argc==0)
82                 return ERROR_OK;
83         if (argc > 1 )
84                 return ERROR_COMMAND_SYNTAX_ERROR;
85         
86         daemon_startup = strcmp("reset", args[0])==0;
87         
88         command_print(cmd_ctx, OPENOCD_VERSION);
89
90         return ERROR_OK;
91 }
92
93 void exit_handler(void)
94 {
95         /* close JTAG interface */
96         if (jtag && jtag->quit)
97                 jtag->quit();
98 }
99
100 /* OpenOCD can't really handle failure of this command. Patches welcome! :-) */
101 int handle_init_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
102 {
103         int retval;
104         static int initialized=0;
105         if (initialized)
106                 return ERROR_OK;
107         
108         initialized=1;
109         
110         command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
111
112         atexit(exit_handler);
113         
114         if (target_init(cmd_ctx) != ERROR_OK)
115                 return ERROR_FAIL;
116         LOG_DEBUG("target init complete");
117
118         if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
119         {
120                 /* we must be able to set up the jtag interface */
121                 return retval;
122         }
123         LOG_DEBUG("jtag interface init complete");
124
125         /* Try to initialize & examine the JTAG chain at this point, but
126          * continue startup regardless */
127         if (jtag_init(cmd_ctx) == ERROR_OK)
128         {
129                 LOG_DEBUG("jtag init complete");
130                 if (target_examine(cmd_ctx) == ERROR_OK)
131                 {
132                         LOG_DEBUG("jtag examine complete");
133                 }
134         }
135         
136         if (flash_init_drivers(cmd_ctx) != ERROR_OK)
137                 return ERROR_FAIL;
138         LOG_DEBUG("flash init complete");
139
140         if (nand_init(cmd_ctx) != ERROR_OK)
141                 return ERROR_FAIL;
142         LOG_DEBUG("NAND init complete");
143
144         if (pld_init(cmd_ctx) != ERROR_OK)
145                 return ERROR_FAIL;
146         LOG_DEBUG("pld init complete");
147
148         /* initialize tcp server */
149         server_init();
150
151         /* initialize telnet subsystem */
152         telnet_init("Open On-Chip Debugger");
153         gdb_init();
154         tcl_init(); /* allows tcl to just connect without going thru telnet */
155
156         return ERROR_OK;
157 }
158
159 Jim_Interp *interp;
160 command_context_t *active_cmd_ctx;
161
162 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
163 {
164         char *namebuf;
165         Jim_Obj *nameObjPtr, *valObjPtr;
166         int result;
167
168         namebuf = alloc_printf("%s(%d)", varname, idx);
169         if (!namebuf)
170                 return JIM_ERR;
171         
172         nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
173         valObjPtr = Jim_NewIntObj(interp, val);
174         if (!nameObjPtr || !valObjPtr)
175         {
176                 free(namebuf);
177                 return JIM_ERR;
178         }
179
180         Jim_IncrRefCount(nameObjPtr);
181         Jim_IncrRefCount(valObjPtr);
182         result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
183         Jim_DecrRefCount(interp, nameObjPtr);
184         Jim_DecrRefCount(interp, valObjPtr);
185         free(namebuf);
186         /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
187         return result;
188 }
189
190 static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
191 {
192         target_t *target;
193         long l;
194         u32 width;
195         u32 len;
196         u32 addr;
197         u32 count;
198         u32 v;
199         const char *varname;
200         u8 buffer[4096];
201         int  i, n, e, retval;
202
203         /* argv[1] = name of array to receive the data
204          * argv[2] = desired width
205          * argv[3] = memory address 
206          * argv[4] = count of times to read
207          */
208         if (argc != 5) {
209                 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
210                 return JIM_ERR;
211         }
212         varname = Jim_GetString(argv[1], &len);
213         /* given "foo" get space for worse case "foo(%d)" .. add 20 */
214
215         e = Jim_GetLong(interp, argv[2], &l);
216         width = l;
217         if (e != JIM_OK) {
218                 return e;
219         }
220         
221         e = Jim_GetLong(interp, argv[3], &l);
222         addr = l;
223         if (e != JIM_OK) {
224                 return e;
225         }
226         e = Jim_GetLong(interp, argv[4], &l);
227         len = l;
228         if (e != JIM_OK) {
229                 return e;
230         }
231         switch (width) {
232                 case 8:
233                         width = 1;
234                         break;
235                 case 16:
236                         width = 2;
237                         break;
238                 case 32:
239                         width = 4;
240                         break;
241                 default:
242                         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
243                         Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
244                         return JIM_ERR;
245         }
246         if (len == 0) {
247                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
248                 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
249                 return JIM_ERR;
250         }
251         if ((addr + (len * width)) < addr) {
252                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
253                 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
254                 return JIM_ERR;
255         }
256         /* absurd transfer size? */
257         if (len > 65536) {
258                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
259                 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
260                 return JIM_ERR;
261         }               
262                 
263         if ((width == 1) ||
264                 ((width == 2) && ((addr & 1) == 0)) ||
265                 ((width == 4) && ((addr & 3) == 0))) {
266                 /* all is well */
267         } else {
268                 char buf[100];
269                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
270                 sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width); 
271                 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
272                 return JIM_ERR;
273         }
274
275         target = get_current_target(active_cmd_ctx);
276         
277         /* Transfer loop */
278
279         /* index counter */
280         n = 0;
281         /* assume ok */
282         e = JIM_OK;
283         while (len) {
284                 /* Slurp... in buffer size chunks */
285                 
286                 count = len; /* in objects.. */
287                 if (count > (sizeof(buffer)/width)) {
288                         count = (sizeof(buffer)/width);
289                 }
290                 
291                 retval = target->type->read_memory( target, addr, width, count, buffer );
292                 if (retval != ERROR_OK) {
293                         /* BOO !*/
294                         LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
295                         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
296                         Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
297                         e = JIM_ERR;
298                         len = 0;
299                 } else {
300                         v = 0; /* shut up gcc */
301                         for (i = 0 ;i < count ;i++, n++) {
302                                 switch (width) {
303                                         case 4:
304                                                 v = target_buffer_get_u32(target, &buffer[i*width]);
305                                                 break;
306                                         case 2:
307                                                 v = target_buffer_get_u16(target, &buffer[i*width]);
308                                                 break;
309                                         case 1:
310                                                 v = buffer[i] & 0x0ff;
311                                                 break;
312                                 }
313                                 new_int_array_element(interp, varname, n, v);
314                         }
315                         len -= count;
316                 }
317         }
318         
319         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
320
321         return JIM_OK;
322 }
323
324 static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)
325 {
326         char *namebuf;
327         Jim_Obj *nameObjPtr, *valObjPtr;
328         int result;
329         long l;
330
331         namebuf = alloc_printf("%s(%d)", varname, idx);
332         if (!namebuf)
333                 return JIM_ERR;
334
335         nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
336         if (!nameObjPtr)
337         {
338                 free(namebuf);
339                 return JIM_ERR;
340         }
341
342         Jim_IncrRefCount(nameObjPtr);
343         valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
344         Jim_DecrRefCount(interp, nameObjPtr);
345         free(namebuf);
346         if (valObjPtr == NULL)
347                 return JIM_ERR;
348
349         result = Jim_GetLong(interp, valObjPtr, &l);
350         /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
351         *val = l;
352         return result;
353 }
354
355 static int Jim_Command_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
356 {
357         target_t *target;
358         long l;
359         u32 width;
360         u32 len;
361         u32 addr;
362         u32 count;
363         u32 v;
364         const char *varname;
365         u8 buffer[4096];
366         int  i, n, e, retval;
367
368         /* argv[1] = name of array to get the data
369          * argv[2] = desired width
370          * argv[3] = memory address 
371          * argv[4] = count to write
372          */
373         if (argc != 5) {
374                 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
375                 return JIM_ERR;
376         }
377         varname = Jim_GetString(argv[1], &len);
378         /* given "foo" get space for worse case "foo(%d)" .. add 20 */
379
380         e = Jim_GetLong(interp, argv[2], &l);
381         width = l;
382         if (e != JIM_OK) {
383                 return e;
384         }
385         
386         e = Jim_GetLong(interp, argv[3], &l);
387         addr = l;
388         if (e != JIM_OK) {
389                 return e;
390         }
391         e = Jim_GetLong(interp, argv[4], &l);
392         len = l;
393         if (e != JIM_OK) {
394                 return e;
395         }
396         switch (width) {
397                 case 8:
398                         width = 1;
399                         break;
400                 case 16:
401                         width = 2;
402                         break;
403                 case 32:
404                         width = 4;
405                         break;
406                 default:
407                         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
408                         Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
409                         return JIM_ERR;
410         }
411         if (len == 0) {
412                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
413                 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
414                 return JIM_ERR;
415         }
416         if ((addr + (len * width)) < addr) {
417                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
418                 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
419                 return JIM_ERR;
420         }
421         /* absurd transfer size? */
422         if (len > 65536) {
423                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
424                 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
425                 return JIM_ERR;
426         }               
427                 
428         if ((width == 1) ||
429                 ((width == 2) && ((addr & 1) == 0)) ||
430                 ((width == 4) && ((addr & 3) == 0))) {
431                 /* all is well */
432         } else {
433                 char buf[100];
434                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
435                 sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width); 
436                 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
437                 return JIM_ERR;
438         }
439
440         target = get_current_target(active_cmd_ctx);
441         
442         /* Transfer loop */
443
444         /* index counter */
445         n = 0;
446         /* assume ok */
447         e = JIM_OK;
448         while (len) {
449                 /* Slurp... in buffer size chunks */
450                 
451                 count = len; /* in objects.. */
452                 if (count > (sizeof(buffer)/width)) {
453                         count = (sizeof(buffer)/width);
454                 }
455
456                 v = 0; /* shut up gcc */
457                 for (i = 0 ;i < count ;i++, n++) {
458                         get_int_array_element(interp, varname, n, &v);
459                         switch (width) {
460                         case 4:
461                                 target_buffer_set_u32(target, &buffer[i*width], v);
462                                 break;
463                         case 2:
464                                 target_buffer_set_u16(target, &buffer[i*width], v);
465                                 break;
466                         case 1:
467                                 buffer[i] = v & 0x0ff;
468                                 break;
469                         }
470                 }
471                 len -= count;
472
473                 retval = target->type->write_memory(target, addr, width, count, buffer);
474                 if (retval != ERROR_OK) {
475                         /* BOO !*/
476                         LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
477                         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
478                         Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
479                         e = JIM_ERR;
480                         len = 0;
481                 }
482         }
483         
484         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
485
486         return JIM_OK;
487 }
488
489 static void tcl_output(void *privData, const char *file, int line, const char *function, const char *string)
490 {               
491         Jim_Obj *tclOutput=(Jim_Obj *)privData;
492
493         Jim_AppendString(interp, tclOutput, string, strlen(string));
494 }
495
496 static int openocd_retval; 
497
498 /* try to execute as Jim command, otherwise fall back to standard command.
499  * Note that even if the Jim command caused an error, then we succeeded
500  * to execute it, hence this fn pretty much always returns ERROR_OK. */
501 int jim_command(command_context_t *context, char *line)
502 {
503         int retval=ERROR_OK;
504         int retcode;
505
506         active_cmd_ctx = context;
507         openocd_retval=ERROR_OK;
508         retcode = Jim_Eval(interp, line);
509         
510         if (retcode == JIM_ERR) {
511                 if (openocd_retval!=ERROR_COMMAND_CLOSE_CONNECTION)
512                 {
513                         /* We do not print the connection closed error message */
514                         Jim_PrintErrorMessage(interp);
515                 }
516                 if (openocd_retval==ERROR_OK)
517                 {
518                         /* It wasn't a low level OpenOCD command that failed */
519                         return ERROR_FAIL; 
520                 }
521             return openocd_retval;
522         } 
523         const char *result;
524         int reslen;
525         result = Jim_GetString(Jim_GetResult(interp), &reslen);
526                 
527         if (retcode == JIM_EXIT) {
528                 /* ignore. */
529         /* exit(Jim_GetExitCode(interp)); */
530         } else {
531                 if (reslen) {
532                         int i;
533                         char buff[256+1];
534                         for (i = 0; i < reslen; i += 256)
535                         {
536                                 int chunk;
537                                 chunk = reslen - i;
538                                 if (chunk > 256)
539                                         chunk = 256;
540                         strncpy(buff, result+i, chunk);
541                                 buff[chunk] = 0; 
542                                 LOG_USER_N("%s", buff);
543                         }
544                         LOG_USER_N("%s", "\n");
545                 }
546         }
547         return retval;
548 }
549
550 int startLoop = 0;
551
552 static int Jim_Command_openocd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int ignore)
553 {
554         int retval;
555         char *cmd = (char*)Jim_GetString(argv[1], NULL);
556         
557         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
558         
559         if (startLoop)
560         {
561                 /* We don't know whether or not the telnet/gdb server is running... */
562                 target_call_timer_callbacks_now();
563         }
564         
565         log_add_callback(tcl_output, tclOutput);
566         retval=command_run_line_internal(active_cmd_ctx, cmd);
567
568         /* we need to be able to get at the retval, so we store in a global variable */
569         openocd_retval=retval;
570         
571         if (startLoop)
572         {
573                 target_call_timer_callbacks_now();
574         }
575         log_remove_callback(tcl_output, tclOutput);
576         
577         Jim_SetResult(interp, tclOutput);
578         
579         return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
580 }
581
582 static int Jim_Command_openocd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
583 {
584         return Jim_Command_openocd_ignore(interp, argc, argv, 1); 
585 }
586
587 static int Jim_Command_openocd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
588 {
589         return Jim_Command_openocd_ignore(interp, argc, argv, 0); 
590 }
591
592 /* find full path to file */
593 static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
594 {
595         if (argc != 2)
596                 return JIM_ERR;
597         const char *file = Jim_GetString(argv[1], NULL);
598         char *full_path = find_file(file);
599         if (full_path == NULL)
600                 return JIM_ERR;
601         Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
602         free(full_path);
603         
604         Jim_SetResult(interp, result);
605         return JIM_OK;
606 }
607
608 static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
609 {
610         if (argc != 2)
611                 return JIM_ERR;
612         char *str = (char*)Jim_GetString(argv[1], NULL);
613         LOG_USER("%s", str);
614         return JIM_OK;
615 }
616
617 static int Jim_Command_script(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
618 {
619         int retval;
620         const char *file;
621         char *full_path;
622
623         if (argc != 2)
624         {
625                 Jim_WrongNumArgs(interp, 1, argv, "file name missing");
626                 return JIM_ERR;
627         }
628
629         /* Run a tcl script file */
630         file = Jim_GetString(argv[1], NULL);
631         full_path = find_file(file);
632         if (full_path == NULL)
633         {
634                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
635                 Jim_AppendStrings(interp, Jim_GetResult(interp), "script: could not open file", file, NULL);
636                 return JIM_ERR;
637         }
638         retval = Jim_EvalFile(interp, full_path);
639         free(full_path);
640         /* convert a return to ok */
641         if (retval == JIM_RETURN)
642                 return JIM_OK;
643         return retval;
644 }
645
646
647 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
648 {
649         size_t nbytes;
650         const char *ptr;
651
652         /* make it a char easier to read code */
653         ptr = _ptr;
654
655         nbytes = size * n;
656         if (nbytes == 0) {
657                 return 0;
658         }
659
660         if (!active_cmd_ctx) {
661                 /* TODO: Where should this go? */               
662                 return n;
663         }
664
665         /* do we have to chunk it? */
666         if (ptr[nbytes] == 0) {
667                 /* no it is a C style string */
668                 command_output_text(active_cmd_ctx, ptr);
669                 return strlen(ptr);
670         }
671         /* GRR we must chunk - not null terminated */
672         while (nbytes) {
673                 char chunk[128+1];
674                 int x;
675
676                 x = nbytes;
677                 if (x > 128) {
678                         x = 128;
679                 }
680                 /* copy it */
681                 memcpy(chunk, ptr, x);
682                 /* terminate it */
683                 chunk[n] = 0;
684                 /* output it */
685                 command_output_text(active_cmd_ctx, chunk);
686                 ptr += x;
687                 nbytes -= x;
688         }
689         
690         return n;
691 }
692
693 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
694 {
695         /* TCL wants to read... tell him no */
696         return 0;
697 }
698
699 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
700 {
701         char *cp;
702         int n;
703         
704         n = -1;
705         if (active_cmd_ctx) {
706                 cp = alloc_vprintf(fmt, ap);
707                 if (cp) {
708                         command_output_text(active_cmd_ctx, cp);
709                         n = strlen(cp);
710                         free(cp);
711                 }
712         }
713         return n;
714 }
715
716 static int openocd_jim_fflush(void *cookie)
717 {
718         /* nothing to flush */
719         return 0;
720 }
721
722 static char* openocd_jim_fgets(char *s, int size, void *cookie)
723 {
724         /* not supported */
725         errno = ENOTSUP;
726         return NULL;
727 }
728
729 void add_jim(const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help)
730 {
731         Jim_CreateCommand(interp, name, cmd, NULL, NULL);
732         
733         /* FIX!!! it would be prettier to invoke add_help_text... 
734         accumulate help text in Tcl helptext list.  */
735     Jim_Obj *helptext=Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
736     if (Jim_IsShared(helptext))
737         helptext = Jim_DuplicateObj(interp, helptext);
738     
739         Jim_Obj *cmd_entry=Jim_NewListObj(interp, NULL, 0);
740         
741         Jim_Obj *cmd_list=Jim_NewListObj(interp, NULL, 0);
742         Jim_ListAppendElement(interp, cmd_list, Jim_NewStringObj(interp, name, -1));
743         
744         Jim_ListAppendElement(interp, cmd_entry, cmd_list);
745         Jim_ListAppendElement(interp, cmd_entry, Jim_NewStringObj(interp, help, -1));
746         Jim_ListAppendElement(interp, helptext, cmd_entry);
747 }
748
749 extern unsigned const char startup_tcl[];
750
751 void initJim(void)
752 {       
753         Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
754         Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
755         Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
756         Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
757         Jim_CreateCommand(interp, "script", Jim_Command_script, NULL, NULL);
758         Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
759         Jim_CreateCommand(interp, "array2mem", Jim_Command_array2mem, NULL, NULL );
760
761         /* Set Jim's STDIO */
762         interp->cookie_stdin = NULL;
763         interp->cookie_stdout = NULL;
764         interp->cookie_stderr = NULL;
765         interp->cb_fwrite = openocd_jim_fwrite;
766         interp->cb_fread = openocd_jim_fread ;
767         interp->cb_vfprintf = openocd_jim_vfprintf;
768         interp->cb_fflush = openocd_jim_fflush;
769         interp->cb_fgets = openocd_jim_fgets;
770         
771         add_default_dirs();
772         
773         if (Jim_Eval(interp, startup_tcl)==JIM_ERR)
774         {
775                 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
776                 Jim_PrintErrorMessage(interp);
777                 exit(-1);
778         }
779 }
780
781 command_context_t *setup_command_handler(void)
782 {
783         command_context_t *cmd_ctx;
784         
785         cmd_ctx = command_init();
786         
787         register_command(cmd_ctx, NULL, "version", handle_version_command,
788                                          COMMAND_EXEC, "show OpenOCD version");
789         register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, 
790                         "deprecated - use \"init\" and \"reset\" at end of startup script instead");
791         
792         /* register subsystem commands */
793         server_register_commands(cmd_ctx);
794         telnet_register_commands(cmd_ctx);
795         gdb_register_commands(cmd_ctx);
796         tcl_register_commands(cmd_ctx); /* tcl server commands */
797         log_register_commands(cmd_ctx);
798         jtag_register_commands(cmd_ctx);
799         xsvf_register_commands(cmd_ctx);
800         target_register_commands(cmd_ctx);
801         flash_register_commands(cmd_ctx);
802         nand_register_commands(cmd_ctx);
803         pld_register_commands(cmd_ctx);
804         
805         if (log_init(cmd_ctx) != ERROR_OK)
806         {
807                 exit(-1);
808         }
809         LOG_DEBUG("log init complete");
810
811         LOG_OUTPUT( OPENOCD_VERSION "\n" );
812         
813         
814         register_command(cmd_ctx, NULL, "init", handle_init_command,
815                                          COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
816
817         return cmd_ctx;
818 }
819
820 /* normally this is the main() function entry, but if OpenOCD is linked
821  * into application, then this fn will not be invoked, but rather that
822  * application will have it's own implementation of main(). */
823 int openocd_main(int argc, char *argv[])
824 {
825 #ifdef JIM_EMBEDDED
826         Jim_InitEmbedded();
827         /* Create an interpreter */
828         interp = Jim_CreateInterp();
829         /* Add all the Jim core commands */
830         Jim_RegisterCoreCommands(interp);
831 #endif
832         
833         initJim();
834         
835         /* initialize commandline interface */
836         command_context_t *cmd_ctx;
837         cmd_ctx=setup_command_handler();
838         
839         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
840         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
841         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
842         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
843         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
844         LOG_OUTPUT( "$URL$\n");
845         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
846         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
847         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
848         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
849         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
850
851         command_context_t *cfg_cmd_ctx;
852         cfg_cmd_ctx = copy_command_context(cmd_ctx);
853         cfg_cmd_ctx->mode = COMMAND_CONFIG;
854         command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
855         
856         active_cmd_ctx=cfg_cmd_ctx;
857         
858
859         if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
860                 return EXIT_FAILURE;
861         
862         if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
863                 return EXIT_FAILURE;
864         
865         active_cmd_ctx=cmd_ctx;
866         
867         command_done(cfg_cmd_ctx);
868
869         if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
870                 return EXIT_FAILURE;
871         
872         if (daemon_startup)
873                 command_run_line(cmd_ctx, "reset");
874         
875         startLoop=1;
876
877         /* handle network connections */
878         server_loop(cmd_ctx);
879
880         /* shut server down */
881         server_quit();
882
883         unregister_all_commands(cmd_ctx);
884         
885         /* free commandline interface */
886         command_done(cmd_ctx);
887
888         return EXIT_SUCCESS;
889 }