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