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

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)