6c1f57031ee13b70f70d70c70fd0e8236c5e4616
[openocd.git] / 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 /* try to execute as Jim command, otherwise fall back to standard command.
497 * Note that even if the Jim command caused an error, then we succeeded
498 * to execute it, hence this fn pretty much always returns ERROR_OK. */
499 int jim_command(command_context_t *context, char *line)
500 {
501 int retval=ERROR_OK;
502 int retcode;
503
504 active_cmd_ctx = context;
505 retcode = Jim_Eval(interp, line);
506
507 if (retcode == JIM_ERR) {
508 Jim_PrintErrorMessage(interp);
509 long t;
510 Jim_Obj *openocd_result=Jim_GetVariableStr(interp, "openocd_result", JIM_ERRMSG);
511 if (openocd_result)
512 {
513 if (Jim_GetLong(interp, openocd_result, &t)==JIM_OK)
514 {
515 return t;
516 }
517 }
518 return ERROR_FAIL;
519 }
520 const char *result;
521 int reslen;
522 result = Jim_GetString(Jim_GetResult(interp), &reslen);
523
524 if (retcode == JIM_EXIT) {
525 /* ignore. */
526 /* exit(Jim_GetExitCode(interp)); */
527 } else {
528 if (reslen) {
529 int i;
530 char buff[256+1];
531 for (i = 0; i < reslen; i += 256)
532 {
533 int chunk;
534 chunk = reslen - i;
535 if (chunk > 256)
536 chunk = 256;
537 strncpy(buff, result+i, chunk);
538 buff[chunk] = 0;
539 LOG_USER_N("%s", buff);
540 }
541 LOG_USER_N("%s", "\n");
542 }
543 }
544 return retval;
545 }
546
547 int startLoop = 0;
548
549 static int Jim_Command_openocd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int ignore)
550 {
551 int retval;
552 char *cmd = (char*)Jim_GetString(argv[1], NULL);
553
554 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
555
556 if (startLoop)
557 {
558 /* We don't know whether or not the telnet/gdb server is running... */
559 target_call_timer_callbacks_now();
560 }
561
562 log_add_callback(tcl_output, tclOutput);
563 retval=command_run_line_internal(active_cmd_ctx, cmd);
564
565 /* we need to be able to get at the retval, so we store in a variable
566 */
567 Jim_Obj *resultvar=Jim_NewIntObj(interp, retval);
568 Jim_IncrRefCount(resultvar);
569 Jim_SetGlobalVariableStr(interp, "openocd_result", resultvar);
570 Jim_DecrRefCount(interp, resultvar);
571
572 if (startLoop)
573 {
574 target_call_timer_callbacks_now();
575 }
576 log_remove_callback(tcl_output, tclOutput);
577
578 Jim_SetResult(interp, tclOutput);
579
580 return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
581 }
582
583 static int Jim_Command_openocd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
584 {
585 return Jim_Command_openocd_ignore(interp, argc, argv, 1);
586 }
587
588 static int Jim_Command_openocd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
589 {
590 return Jim_Command_openocd_ignore(interp, argc, argv, 0);
591 }
592
593 /* find full path to file */
594 static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
595 {
596 if (argc != 2)
597 return JIM_ERR;
598 char *file = (char*)Jim_GetString(argv[1], NULL);
599 char *full_path = find_file(file);
600 if (full_path == NULL)
601 return JIM_ERR;
602 Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
603 free(full_path);
604
605 Jim_SetResult(interp, result);
606 return JIM_OK;
607 }
608
609 static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
610 {
611 if (argc != 2)
612 return JIM_ERR;
613 char *str = (char*)Jim_GetString(argv[1], NULL);
614 LOG_USER("%s", str);
615 return JIM_OK;
616 }
617
618 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
619 {
620 size_t nbytes;
621 const char *ptr;
622
623 /* make it a char easier to read code */
624 ptr = _ptr;
625
626 nbytes = size * n;
627 if (nbytes == 0) {
628 return 0;
629 }
630
631 if (!active_cmd_ctx) {
632 /* TODO: Where should this go? */
633 return n;
634 }
635
636 /* do we have to chunk it? */
637 if (ptr[nbytes] == 0) {
638 /* no it is a C style string */
639 command_output_text(active_cmd_ctx, ptr);
640 return strlen(ptr);
641 }
642 /* GRR we must chunk - not null terminated */
643 while (nbytes) {
644 char chunk[128+1];
645 int x;
646
647 x = nbytes;
648 if (x > 128) {
649 x = 128;
650 }
651 /* copy it */
652 memcpy(chunk, ptr, x);
653 /* terminate it */
654 chunk[n] = 0;
655 /* output it */
656 command_output_text(active_cmd_ctx, chunk);
657 ptr += x;
658 nbytes -= x;
659 }
660
661 return n;
662 }
663
664 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
665 {
666 /* TCL wants to read... tell him no */
667 return 0;
668 }
669
670 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
671 {
672 char *cp;
673 int n;
674
675 n = -1;
676 if (active_cmd_ctx) {
677 cp = alloc_vprintf(fmt, ap);
678 if (cp) {
679 command_output_text(active_cmd_ctx, cp);
680 n = strlen(cp);
681 free(cp);
682 }
683 }
684 return n;
685 }
686
687 static int openocd_jim_fflush(void *cookie)
688 {
689 /* nothing to flush */
690 return 0;
691 }
692
693 static char* openocd_jim_fgets(char *s, int size, void *cookie)
694 {
695 /* not supported */
696 errno = ENOTSUP;
697 return NULL;
698 }
699
700 void add_jim(const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help)
701 {
702 Jim_CreateCommand(interp, name, cmd, NULL, NULL);
703
704 /* FIX!!! it would be prettier to invoke add_help_text...
705 accumulate help text in Tcl helptext list. */
706 Jim_Obj *helptext=Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
707 Jim_Obj *cmd_entry=Jim_NewListObj(interp, NULL, 0);
708
709 Jim_Obj *cmd_list=Jim_NewListObj(interp, NULL, 0);
710 Jim_ListAppendElement(interp, cmd_list, Jim_NewStringObj(interp, name, -1));
711
712 Jim_ListAppendElement(interp, cmd_entry, cmd_list);
713 Jim_ListAppendElement(interp, cmd_entry, Jim_NewStringObj(interp, help, -1));
714 Jim_ListAppendElement(interp, helptext, cmd_entry);
715 }
716
717 extern char binary_startup_tcl_start;
718 extern char binary_startup_tcl_size;
719
720 void initJim(void)
721 {
722 char *script;
723 int script_len;
724
725 Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
726 Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
727 Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
728 Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
729 Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
730 Jim_CreateCommand(interp, "array2mem", Jim_Command_array2mem, NULL, NULL );
731
732 /* Set Jim's STDIO */
733 interp->cookie_stdin = NULL;
734 interp->cookie_stdout = NULL;
735 interp->cookie_stderr = NULL;
736 interp->cb_fwrite = openocd_jim_fwrite;
737 interp->cb_fread = openocd_jim_fread ;
738 interp->cb_vfprintf = openocd_jim_vfprintf;
739 interp->cb_fflush = openocd_jim_fflush;
740 interp->cb_fgets = openocd_jim_fgets;
741
742 add_default_dirs();
743
744 script_len = (int)&binary_startup_tcl_size;
745 script = malloc(script_len + sizeof(char));
746 memcpy(script, &binary_startup_tcl_start, script_len);
747
748 /* null terminate */
749 script[script_len] = 0;
750
751 if (Jim_Eval(interp, script)==JIM_ERR)
752 {
753 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
754 Jim_PrintErrorMessage(interp);
755 exit(-1);
756 }
757
758 free(script);
759 }
760
761 int handle_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
762 {
763 if (argc != 1)
764 return ERROR_COMMAND_SYNTAX_ERROR;
765
766 /* Run a tcl script file */
767 return command_run_linef(cmd_ctx, "source [find {%s}]", args[0]);
768 }
769
770 command_context_t *setup_command_handler(void)
771 {
772 command_context_t *cmd_ctx;
773
774 cmd_ctx = command_init();
775
776 register_command(cmd_ctx, NULL, "version", handle_version_command,
777 COMMAND_EXEC, "show OpenOCD version");
778 register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG,
779 "deprecated - use \"init\" and \"reset\" at end of startup script instead");
780
781 /* register subsystem commands */
782 server_register_commands(cmd_ctx);
783 telnet_register_commands(cmd_ctx);
784 gdb_register_commands(cmd_ctx);
785 tcl_register_commands(cmd_ctx); /* tcl server commands */
786 log_register_commands(cmd_ctx);
787 jtag_register_commands(cmd_ctx);
788 register_command(cmd_ctx, NULL, "script", handle_script_command, COMMAND_ANY, "execute commands from <file>");
789 xsvf_register_commands(cmd_ctx);
790 target_register_commands(cmd_ctx);
791 flash_register_commands(cmd_ctx);
792 nand_register_commands(cmd_ctx);
793 pld_register_commands(cmd_ctx);
794
795 if (log_init(cmd_ctx) != ERROR_OK)
796 {
797 exit(-1);
798 }
799 LOG_DEBUG("log init complete");
800
801 LOG_OUTPUT( OPENOCD_VERSION "\n" );
802
803
804 register_command(cmd_ctx, NULL, "init", handle_init_command,
805 COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
806
807 return cmd_ctx;
808 }
809
810 /* normally this is the main() function entry, but if OpenOCD is linked
811 * into application, then this fn will not be invoked, but rather that
812 * application will have it's own implementation of main(). */
813 int openocd_main(int argc, char *argv[])
814 {
815 #ifdef JIM_EMBEDDED
816 Jim_InitEmbedded();
817 /* Create an interpreter */
818 interp = Jim_CreateInterp();
819 /* Add all the Jim core commands */
820 Jim_RegisterCoreCommands(interp);
821 #endif
822
823 initJim();
824
825 /* initialize commandline interface */
826 command_context_t *cmd_ctx;
827 cmd_ctx=setup_command_handler();
828
829 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
830 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
831 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
832 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
833 /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
834 LOG_OUTPUT( "$URL$\n");
835 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
836 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
837 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
838 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
839 /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
840
841 command_context_t *cfg_cmd_ctx;
842 cfg_cmd_ctx = copy_command_context(cmd_ctx);
843 cfg_cmd_ctx->mode = COMMAND_CONFIG;
844 command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
845
846 active_cmd_ctx=cfg_cmd_ctx;
847
848
849 if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
850 return EXIT_FAILURE;
851
852 if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
853 return EXIT_FAILURE;
854
855 active_cmd_ctx=cmd_ctx;
856
857 command_done(cfg_cmd_ctx);
858
859 if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
860 return EXIT_FAILURE;
861
862 if (daemon_startup)
863 command_run_line(cmd_ctx, "reset");
864
865 startLoop=1;
866
867 /* handle network connections */
868 server_loop(cmd_ctx);
869
870 /* shut server down */
871 server_quit();
872
873 unregister_all_commands(cmd_ctx);
874
875 /* free commandline interface */
876 command_done(cmd_ctx);
877
878 return EXIT_SUCCESS;
879 }