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