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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)