]> git.sur5r.net Git - openocd/blob - src/openocd.c
6bf163f5b040bae79a00a6a5b971dccfe8733990
[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          */
156         if (jtag_init(cmd_ctx) == ERROR_OK)
157         {
158                 LOG_DEBUG("jtag init complete");
159                 if (target_examine(cmd_ctx) == ERROR_OK)
160                 {
161                         LOG_DEBUG("jtag examine complete");
162                 }
163         }
164         
165         if (flash_init_drivers(cmd_ctx) != ERROR_OK)
166                 return ERROR_FAIL;
167         LOG_DEBUG("flash init complete");
168
169         if (nand_init(cmd_ctx) != ERROR_OK)
170                 return ERROR_FAIL;
171         LOG_DEBUG("NAND init complete");
172
173         if (pld_init(cmd_ctx) != ERROR_OK)
174                 return ERROR_FAIL;
175         LOG_DEBUG("pld init complete");
176
177         /* initialize tcp server */
178         server_init();
179
180         /* initialize telnet subsystem */
181         telnet_init("Open On-Chip Debugger");
182         gdb_init();
183         tcl_init(); /* allows tcl to just connect without going thru telnet */
184
185         return ERROR_OK;
186 }
187
188
189 Jim_Interp *interp;
190 command_context_t *active_cmd_ctx;
191
192 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
193 {
194         char *namebuf;
195         Jim_Obj *nameObjPtr, *valObjPtr;
196         int result;
197
198         namebuf = alloc_printf("%s(%d)", varname, idx );
199         
200     nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
201     valObjPtr = Jim_NewIntObj(interp, val );
202     Jim_IncrRefCount(nameObjPtr);
203     Jim_IncrRefCount(valObjPtr);
204     result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
205     Jim_DecrRefCount(interp, nameObjPtr);
206     Jim_DecrRefCount(interp, valObjPtr);
207     free(namebuf);
208         // printf( "%s = 0%08x\n", namebuf, val );
209     return result;
210 }
211
212 static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
213 {
214         target_t *target;
215         long l;
216         u32 width;
217         u32 len;
218         u32 addr;
219         u32 count;
220         u32 v;
221         const char *varname;
222         u8 buffer[4096];
223         int  i,n,e,retval;
224
225         /* argv[1] = name of array to receive the data
226          * argv[2] = desired width
227          * argv[3] = memory address 
228          * argv[4] = length in bytes to read
229          */
230         if( argc != 5 ){
231                 Jim_WrongNumArgs( interp, 1, argv, "varname width addr nelems" );
232                 return JIM_ERR;
233         }
234         varname = Jim_GetString( argv[1], &len );
235         /* given "foo" get space for worse case "foo(%d)" .. add 20 */
236
237         e = Jim_GetLong( interp, argv[2], &l );
238         width = l;
239         if( e != JIM_OK ){
240                 return e;
241         }
242         
243         e = Jim_GetLong( interp, argv[3], &l );
244         addr = l;
245         if( e != JIM_OK ){
246                 return e;
247         }
248         e = Jim_GetLong( interp, argv[4], &l );
249         len = l;
250         if( e != JIM_OK ){
251                 return e;
252         }
253         switch(width){
254         case 8:
255                 width = 1;
256                 break;
257         case 16:
258                 width = 2;
259                 break;
260         case 32:
261                 width = 4;
262                 break;
263         default:
264                 Jim_SetResult(interp, 
265                                           Jim_NewEmptyStringObj(interp));
266                 Jim_AppendStrings( interp, Jim_GetResult(interp),
267                                                    "Invalid width param, must be 8/16/32", NULL );
268                 return JIM_ERR;
269         }
270         if( len == 0 ){
271                 Jim_SetResult(interp, 
272                                           Jim_NewEmptyStringObj(interp));
273                 Jim_AppendStrings( interp, Jim_GetResult(interp),
274                                                    "mem2array: zero width read?", NULL );
275                 return JIM_ERR;
276         }
277         if( (addr + (len * width)) < addr ){
278                 Jim_SetResult(interp, 
279                                           Jim_NewEmptyStringObj(interp));
280                 Jim_AppendStrings( interp, Jim_GetResult(interp),
281                                                    "mem2array: addr + len - wraps to zero?", NULL );
282                 return JIM_ERR;
283         }
284         /* absurd transfer size? */
285         if( len > 65536 ){
286                 Jim_SetResult(interp, 
287                                           Jim_NewEmptyStringObj(interp));
288                 Jim_AppendStrings( interp, Jim_GetResult(interp),
289                                                    "mem2array: absurd > 64K item request", NULL );
290                 return JIM_ERR;
291         }               
292                 
293         if( (width == 1) ||
294                 ((width == 2) && ((addr & 1) == 0)) ||
295                 ((width == 4) && ((addr & 3) == 0)) ){
296                 /* all is well */
297         } else {
298                 char buf[100];
299                 Jim_SetResult(interp, 
300                                           Jim_NewEmptyStringObj(interp));
301                 sprintf( buf, 
302                                  "mem2array address: 0x%08x is not aligned for %d byte reads",
303                                  addr, width );
304                                  
305                 Jim_AppendStrings( interp, Jim_GetResult(interp),
306                                                    buf , NULL );
307                 return JIM_ERR;
308         }
309
310         target = get_current_target( active_cmd_ctx );
311         
312         /* Transfer loop */
313
314         /* index counter */
315         n = 0;
316         /* assume ok */
317         e = JIM_OK;
318         while( len ){
319
320                 /* Slurp... in buffer size chunks */
321                 
322                 count = len; /* in objects.. */
323                 if( count > (sizeof(buffer)/width)){
324                         count = (sizeof(buffer)/width);
325                 }
326                 
327                 retval = target->type->read_memory( target, 
328                                                                                         addr, 
329                                                                                         width, 
330                                                                                         count,
331                                                                                         buffer );
332
333                 if( retval != ERROR_OK ){
334                         /* BOO !*/
335                         LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed",
336                                           addr, width, count );
337                         Jim_SetResult(interp, 
338                                                   Jim_NewEmptyStringObj(interp));
339                         Jim_AppendStrings( interp, Jim_GetResult(interp),
340                                                    "mem2array: cannot read memory", NULL );
341                         e = JIM_ERR;
342                         len = 0;
343                 } else {
344                         v = 0; /* shut up gcc */
345                         for( i = 0 ; i < count ; i++, n++ ){
346                                 switch(width){
347                                 case 4:
348                                         v = target_buffer_get_u32( target, &buffer[i*width] );
349                                         break;
350                                 case 2:
351                                         v = target_buffer_get_u16( target, &buffer[i*width] );
352                                         break;
353                                 case 1:
354                                         v = buffer[i] & 0x0ff;
355                                         break;
356                                 }
357                                 new_int_array_element( interp, varname, n, v );
358                         }
359                         len -= count;
360                 }
361         }
362         Jim_SetResult(interp, 
363                                   Jim_NewEmptyStringObj(interp));
364
365         return JIM_OK;
366 }
367
368 static void tcl_output(void *privData, const char *file, int line, const char *function, const char *string)
369 {               
370         Jim_Obj *tclOutput=(Jim_Obj *)privData;
371
372         Jim_AppendString(interp, tclOutput, string, strlen(string));
373 }
374
375 /* try to execute as Jim command, otherwise fall back to standard command.
376
377         Note that even if the Jim command caused an error, then we succeeded
378         to execute it, hence this fn pretty much always returns ERROR_OK. 
379
380  */
381 int jim_command(command_context_t *context, char *line)
382 {
383         int retval=ERROR_OK;
384         int retcode=Jim_Eval(interp, line);
385         
386         const char *result;
387         int reslen;
388     result = Jim_GetString(Jim_GetResult(interp), &reslen);
389     if (retcode == JIM_ERR) {
390             int len, i;
391         
392             LOG_USER_N("Runtime error, file \"%s\", line %d:" JIM_NL,
393                     interp->errorFileName, interp->errorLine);
394             LOG_USER_N("    %s" JIM_NL,
395                     Jim_GetString(interp->result, NULL));
396             Jim_ListLength(interp, interp->stackTrace, &len);
397             for (i = 0; i < len; i+= 3) {
398                 Jim_Obj *objPtr;
399                 const char *proc, *file, *line;
400         
401                 Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
402                 proc = Jim_GetString(objPtr, NULL);
403                 Jim_ListIndex(interp, interp->stackTrace, i+1, &objPtr,
404                         JIM_NONE);
405                 file = Jim_GetString(objPtr, NULL);
406                 Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr,
407                         JIM_NONE);
408                 line = Jim_GetString(objPtr, NULL);
409                 LOG_USER_N("In procedure '%s' called at file \"%s\", line %s" JIM_NL,
410                         proc, file, line);
411             }
412     } else if (retcode == JIM_EXIT) {
413         // ignore.
414         //exit(Jim_GetExitCode(interp));
415     } else {
416         if (reslen) {
417                 int i;
418                 char buff[256+1];
419                 for (i=0; i<reslen; i+=256)
420                 {
421                         int chunk;
422                         chunk=reslen-i;
423                         if (chunk>256)
424                                 chunk=256;
425                         strncpy(buff, result, chunk);
426                         buff[chunk]=0; 
427                 LOG_USER_N("%s", buff);
428                 }
429                 LOG_USER_N("%s", "\n");
430         }
431     }
432         return retval;
433 }
434
435 int startLoop=0;
436
437 static int Jim_Command_openocd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int ignore)
438 {
439         int retval;
440     char *cmd = (char*)Jim_GetString(argv[1], NULL);
441
442     Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
443     
444     if (startLoop)
445     {
446         // We don't know whether or not the telnet/gdb server is running...
447         target_call_timer_callbacks_now();
448     }
449         
450         log_add_callback(tcl_output, tclOutput);
451     retval=command_run_line_internal(active_cmd_ctx, cmd);
452     
453     if (startLoop)
454     {
455         target_call_timer_callbacks_now();
456     }
457         log_remove_callback(tcl_output, tclOutput);
458     
459         Jim_SetResult(interp, tclOutput);
460         
461     return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
462 }
463
464 static int Jim_Command_openocd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
465 {
466         return Jim_Command_openocd_ignore(interp, argc, argv, 1); 
467 }
468
469 static int Jim_Command_openocd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
470 {
471         return Jim_Command_openocd_ignore(interp, argc, argv, 0); 
472 }
473
474 /* find full path to file */
475 static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
476 {
477         if (argc!=2)
478                 return JIM_ERR;
479         char *file = (char*)Jim_GetString(argv[1], NULL);
480         char *full_path=find_file(file);
481         if (full_path==NULL)
482                 return JIM_ERR;
483     Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
484     free(full_path);
485     
486         Jim_SetResult(interp, result);
487         return JIM_OK;
488 }
489
490 static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
491 {
492         if (argc!=2)
493                 return JIM_ERR;
494         char *str = (char*)Jim_GetString(argv[1], NULL);
495         LOG_USER("%s", str);
496         return JIM_OK;
497 }
498
499 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
500 {
501         size_t nbytes;
502         const char *ptr;
503
504         /* make it a char easier to read code */
505         ptr = _ptr;
506
507         nbytes = size * n;
508         if( nbytes == 0 ){
509                 return 0;
510         }
511
512         if( !active_cmd_ctx ){
513                 /* FIXME: Where should this go? */              
514                 return n;
515         }
516
517         /* do we have to chunk it? */
518         if( ptr[ nbytes ] == 0 ){
519                 /* no it is a C style string */
520                 command_output_text( active_cmd_ctx, ptr );
521                 return strlen(ptr);
522         }
523         /* GRR we must chunk - not null terminated */
524         while( nbytes ){
525                 char chunk[128+1];
526                 int x;
527
528                 x = nbytes;
529                 if( x > 128 ){
530                         x = 128;
531                 }
532                 /* copy it */
533                 memcpy( chunk, ptr, x );
534                 /* terminate it */
535                 chunk[n] = 0;
536                 /* output it */
537                 command_output_text( active_cmd_ctx, chunk );
538                 ptr += x;
539                 nbytes -= x;
540         }
541         
542         return n;
543 }
544
545 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
546 {
547         /* TCL wants to read... tell him no */
548         return 0;
549 }
550
551 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
552 {
553         char *cp;
554         int n;
555         
556         n = -1;
557         if( active_cmd_ctx ){
558                 cp = alloc_vprintf( fmt, ap );
559                 if( cp ){
560                         command_output_text( active_cmd_ctx, cp );
561                         n = strlen(cp);
562                         free(cp);
563                 }
564         }
565         return n;
566 }
567
568 static int openocd_jim_fflush(void *cookie)
569 {
570         /* nothing to flush */
571         return 0;
572 }
573
574 static char* openocd_jim_fgets(char *s, int size, void *cookie)
575 {
576         /* not supported */
577         errno = ENOTSUP;
578         return NULL;
579 }
580
581 void initJim(void)
582 {
583     Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
584     Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
585     Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
586     Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
587     Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
588
589         /* Set Jim's STDIO */
590         interp->cookie_stdin  = NULL;
591         interp->cookie_stdout = NULL;
592         interp->cookie_stderr = NULL;
593         interp->cb_fwrite     = openocd_jim_fwrite;
594         interp->cb_fread      = openocd_jim_fread ;
595         interp->cb_vfprintf   = openocd_jim_vfprintf;
596         interp->cb_fflush     = openocd_jim_fflush;
597         interp->cb_fgets      = openocd_jim_fgets;
598 }
599
600 /* after command line parsing */
601 void initJim2(void)
602 {
603         Jim_Eval(interp, "source [find tcl/commands.tcl]");
604 }
605
606 command_context_t *setup_command_handler()
607 {
608         command_context_t *cmd_ctx;
609         
610         cmd_ctx = command_init();
611
612         register_command(cmd_ctx, NULL, "version", handle_version_command,
613                                          COMMAND_EXEC, "show OpenOCD version");
614         register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, 
615                         "deprecated - use \"init\" and \"reset\" at end of startup script instead");
616         
617         /* register subsystem commands */
618         server_register_commands(cmd_ctx);
619         telnet_register_commands(cmd_ctx);
620         gdb_register_commands(cmd_ctx);
621         tcl_register_commands(cmd_ctx); /* tcl server commands */
622         log_register_commands(cmd_ctx);
623         jtag_register_commands(cmd_ctx);
624         interpreter_register_commands(cmd_ctx);
625         xsvf_register_commands(cmd_ctx);
626         target_register_commands(cmd_ctx);
627         flash_register_commands(cmd_ctx);
628         nand_register_commands(cmd_ctx);
629         pld_register_commands(cmd_ctx);
630         
631         if (log_init(cmd_ctx) != ERROR_OK)
632         {
633                 exit(-1);
634         }
635         LOG_DEBUG("log init complete");
636
637         LOG_OUTPUT( OPENOCD_VERSION "\n" );
638         
639         
640         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
641         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
642         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
643         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
644         /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
645         LOG_OUTPUT( "$URL$\n");
646         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
647         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
648         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
649         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
650         /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
651
652         register_command(cmd_ctx, NULL, "init", handle_init_command,
653                                          COMMAND_ANY, "initializes target and servers - nop on subsequent invocations");
654
655         return cmd_ctx;
656 }
657
658 /*
659 normally this is the main() function entry, but if OpenOCD is linked
660 into application, then this fn will not be invoked, but rather that
661 application will have it's own implementation of main().
662 */
663 int openocd_main(int argc, char *argv[])
664 {
665 #ifdef JIM_EMBEDDED
666         Jim_InitEmbedded();
667     /* Create an interpreter */
668     interp = Jim_CreateInterp();
669     /* Add all the Jim core commands */
670     Jim_RegisterCoreCommands(interp);
671 #endif
672     
673         initJim();
674         
675         /* initialize commandline interface */
676         command_context_t *cmd_ctx;
677         cmd_ctx=setup_command_handler();
678         
679         command_context_t *cfg_cmd_ctx;
680         cfg_cmd_ctx = copy_command_context(cmd_ctx);
681         cfg_cmd_ctx->mode = COMMAND_CONFIG;
682         command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
683         
684         active_cmd_ctx=cfg_cmd_ctx;
685         
686         if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
687                 return EXIT_FAILURE;
688
689         initJim2();
690
691         if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
692                 return EXIT_FAILURE;
693         
694         active_cmd_ctx=cmd_ctx;
695         
696         command_done(cfg_cmd_ctx);
697
698         if (command_run_line(cmd_ctx, "init")!=ERROR_OK)
699                 return EXIT_FAILURE;
700         
701         if (daemon_startup)
702                 command_run_line(cmd_ctx, "reset");
703         
704         startLoop=1;
705
706         /* handle network connections */
707         server_loop(cmd_ctx);
708
709         /* shut server down */
710         server_quit();
711
712         unregister_all_commands(cmd_ctx);
713         
714         /* free commandline interface */
715         command_done(cmd_ctx);
716
717         return EXIT_SUCCESS;
718 }