Add wrappers for target->type->examined:
[openocd.git] / src / target / target.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2008, Duane Ellis *
9 * openocd@duaneeellis.com *
10 * *
11 * Copyright (C) 2008 by Spencer Oliver *
12 * spen@spen-soft.co.uk *
13 * *
14 * Copyright (C) 2008 by Rick Altherr *
15 * kc8apf@kc8apf.net> *
16 * *
17 * This program is free software; you can redistribute it and/or modify *
18 * it under the terms of the GNU General Public License as published by *
19 * the Free Software Foundation; either version 2 of the License, or *
20 * (at your option) any later version. *
21 * *
22 * This program is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
25 * GNU General Public License for more details. *
26 * *
27 * You should have received a copy of the GNU General Public License *
28 * along with this program; if not, write to the *
29 * Free Software Foundation, Inc., *
30 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
31 ***************************************************************************/
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "target.h"
37 #include "target_request.h"
38 #include "time_support.h"
39 #include "register.h"
40 #include "trace.h"
41 #include "image.h"
42 #include "jtag.h"
43
44 #include <inttypes.h>
45
46
47 static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
48
49 static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
50 static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
51 static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
52 static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
53 static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
54 static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
55 static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
56 static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
57 static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
58 static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
59 static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
60 static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
61 static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
62 static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
63 static int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
64 static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
65 static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
66 static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
67 static int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
68 static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
69 static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
70 static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
71
72 static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
73 static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
74 static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv);
75
76 static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv);
77 static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv);
78
79 /* targets */
80 extern target_type_t arm7tdmi_target;
81 extern target_type_t arm720t_target;
82 extern target_type_t arm9tdmi_target;
83 extern target_type_t arm920t_target;
84 extern target_type_t arm966e_target;
85 extern target_type_t arm926ejs_target;
86 extern target_type_t feroceon_target;
87 extern target_type_t xscale_target;
88 extern target_type_t cortexm3_target;
89 extern target_type_t cortexa8_target;
90 extern target_type_t arm11_target;
91 extern target_type_t mips_m4k_target;
92 extern target_type_t avr_target;
93
94 target_type_t *target_types[] =
95 {
96 &arm7tdmi_target,
97 &arm9tdmi_target,
98 &arm920t_target,
99 &arm720t_target,
100 &arm966e_target,
101 &arm926ejs_target,
102 &feroceon_target,
103 &xscale_target,
104 &cortexm3_target,
105 &cortexa8_target,
106 &arm11_target,
107 &mips_m4k_target,
108 &avr_target,
109 NULL,
110 };
111
112 target_t *all_targets = NULL;
113 target_event_callback_t *target_event_callbacks = NULL;
114 target_timer_callback_t *target_timer_callbacks = NULL;
115
116 const Jim_Nvp nvp_assert[] = {
117 { .name = "assert", NVP_ASSERT },
118 { .name = "deassert", NVP_DEASSERT },
119 { .name = "T", NVP_ASSERT },
120 { .name = "F", NVP_DEASSERT },
121 { .name = "t", NVP_ASSERT },
122 { .name = "f", NVP_DEASSERT },
123 { .name = NULL, .value = -1 }
124 };
125
126 const Jim_Nvp nvp_error_target[] = {
127 { .value = ERROR_TARGET_INVALID, .name = "err-invalid" },
128 { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" },
129 { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
130 { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" },
131 { .value = ERROR_TARGET_FAILURE, .name = "err-failure" },
132 { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" },
133 { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" },
134 { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" },
135 { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" },
136 { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" },
137 { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" },
138 { .value = -1, .name = NULL }
139 };
140
141 const char *target_strerror_safe( int err )
142 {
143 const Jim_Nvp *n;
144
145 n = Jim_Nvp_value2name_simple( nvp_error_target, err );
146 if( n->name == NULL ){
147 return "unknown";
148 } else {
149 return n->name;
150 }
151 }
152
153 static const Jim_Nvp nvp_target_event[] = {
154 { .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
155 { .value = TARGET_EVENT_OLD_pre_resume , .name = "old-pre_resume" },
156
157 { .value = TARGET_EVENT_EARLY_HALTED, .name = "early-halted" },
158 { .value = TARGET_EVENT_HALTED, .name = "halted" },
159 { .value = TARGET_EVENT_RESUMED, .name = "resumed" },
160 { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
161 { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" },
162
163 { .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
164 { .name = "gdb-end", .value = TARGET_EVENT_GDB_END },
165
166 /* historical name */
167
168 { .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
169
170 { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" },
171 { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" },
172 { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" },
173 { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
174 { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" },
175 { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" },
176 { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" },
177 { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" },
178 { .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" },
179 { .value = TARGET_EVENT_RESET_END, .name = "reset-end" },
180
181 { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
182 { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
183
184 { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
185 { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" },
186
187 { .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" },
188 { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" },
189
190 { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" },
191 { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" },
192
193 { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
194 { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" },
195
196 { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
197 { .value = TARGET_EVENT_RESUMED , .name = "resume-ok" },
198 { .value = TARGET_EVENT_RESUME_END , .name = "resume-end" },
199
200 { .name = NULL, .value = -1 }
201 };
202
203 const Jim_Nvp nvp_target_state[] = {
204 { .name = "unknown", .value = TARGET_UNKNOWN },
205 { .name = "running", .value = TARGET_RUNNING },
206 { .name = "halted", .value = TARGET_HALTED },
207 { .name = "reset", .value = TARGET_RESET },
208 { .name = "debug-running", .value = TARGET_DEBUG_RUNNING },
209 { .name = NULL, .value = -1 },
210 };
211
212 const Jim_Nvp nvp_target_debug_reason [] = {
213 { .name = "debug-request" , .value = DBG_REASON_DBGRQ },
214 { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT },
215 { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT },
216 { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
217 { .name = "single-step" , .value = DBG_REASON_SINGLESTEP },
218 { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED },
219 { .name = "undefined" , .value = DBG_REASON_UNDEFINED },
220 { .name = NULL, .value = -1 },
221 };
222
223 const Jim_Nvp nvp_target_endian[] = {
224 { .name = "big", .value = TARGET_BIG_ENDIAN },
225 { .name = "little", .value = TARGET_LITTLE_ENDIAN },
226 { .name = "be", .value = TARGET_BIG_ENDIAN },
227 { .name = "le", .value = TARGET_LITTLE_ENDIAN },
228 { .name = NULL, .value = -1 },
229 };
230
231 const Jim_Nvp nvp_reset_modes[] = {
232 { .name = "unknown", .value = RESET_UNKNOWN },
233 { .name = "run" , .value = RESET_RUN },
234 { .name = "halt" , .value = RESET_HALT },
235 { .name = "init" , .value = RESET_INIT },
236 { .name = NULL , .value = -1 },
237 };
238
239 static int max_target_number(void)
240 {
241 target_t *t;
242 int x;
243
244 x = -1;
245 t = all_targets;
246 while( t ){
247 if( x < t->target_number ){
248 x = (t->target_number)+1;
249 }
250 t = t->next;
251 }
252 return x;
253 }
254
255 /* determine the number of the new target */
256 static int new_target_number(void)
257 {
258 target_t *t;
259 int x;
260
261 /* number is 0 based */
262 x = -1;
263 t = all_targets;
264 while(t){
265 if( x < t->target_number ){
266 x = t->target_number;
267 }
268 t = t->next;
269 }
270 return x+1;
271 }
272
273 static int target_continous_poll = 1;
274
275 /* read a u32 from a buffer in target memory endianness */
276 u32 target_buffer_get_u32(target_t *target, const u8 *buffer)
277 {
278 if (target->endianness == TARGET_LITTLE_ENDIAN)
279 return le_to_h_u32(buffer);
280 else
281 return be_to_h_u32(buffer);
282 }
283
284 /* read a u16 from a buffer in target memory endianness */
285 u16 target_buffer_get_u16(target_t *target, const u8 *buffer)
286 {
287 if (target->endianness == TARGET_LITTLE_ENDIAN)
288 return le_to_h_u16(buffer);
289 else
290 return be_to_h_u16(buffer);
291 }
292
293 /* read a u8 from a buffer in target memory endianness */
294 u8 target_buffer_get_u8(target_t *target, const u8 *buffer)
295 {
296 return *buffer & 0x0ff;
297 }
298
299 /* write a u32 to a buffer in target memory endianness */
300 void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
301 {
302 if (target->endianness == TARGET_LITTLE_ENDIAN)
303 h_u32_to_le(buffer, value);
304 else
305 h_u32_to_be(buffer, value);
306 }
307
308 /* write a u16 to a buffer in target memory endianness */
309 void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
310 {
311 if (target->endianness == TARGET_LITTLE_ENDIAN)
312 h_u16_to_le(buffer, value);
313 else
314 h_u16_to_be(buffer, value);
315 }
316
317 /* write a u8 to a buffer in target memory endianness */
318 void target_buffer_set_u8(target_t *target, u8 *buffer, u8 value)
319 {
320 *buffer = value;
321 }
322
323 /* return a pointer to a configured target; id is name or number */
324 target_t *get_target(const char *id)
325 {
326 target_t *target;
327 char *endptr;
328 int num;
329
330 /* try as tcltarget name */
331 for (target = all_targets; target; target = target->next) {
332 if (target->cmd_name == NULL)
333 continue;
334 if (strcmp(id, target->cmd_name) == 0)
335 return target;
336 }
337
338 /* no match, try as number */
339 num = strtoul(id, &endptr, 0);
340 if (*endptr != 0)
341 return NULL;
342
343 for (target = all_targets; target; target = target->next) {
344 if (target->target_number == num)
345 return target;
346 }
347
348 return NULL;
349 }
350
351 /* returns a pointer to the n-th configured target */
352 static target_t *get_target_by_num(int num)
353 {
354 target_t *target = all_targets;
355
356 while (target){
357 if( target->target_number == num ){
358 return target;
359 }
360 target = target->next;
361 }
362
363 return NULL;
364 }
365
366 int get_num_by_target(target_t *query_target)
367 {
368 return query_target->target_number;
369 }
370
371 target_t* get_current_target(command_context_t *cmd_ctx)
372 {
373 target_t *target = get_target_by_num(cmd_ctx->current_target);
374
375 if (target == NULL)
376 {
377 LOG_ERROR("BUG: current_target out of bounds");
378 exit(-1);
379 }
380
381 return target;
382 }
383
384 int target_poll(struct target_s *target)
385 {
386 /* We can't poll until after examine */
387 if (!target_was_examined(target))
388 {
389 /* Fail silently lest we pollute the log */
390 return ERROR_FAIL;
391 }
392 return target->type->poll(target);
393 }
394
395 int target_halt(struct target_s *target)
396 {
397 /* We can't poll until after examine */
398 if (!target_was_examined(target))
399 {
400 LOG_ERROR("Target not examined yet");
401 return ERROR_FAIL;
402 }
403 return target->type->halt(target);
404 }
405
406 int target_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
407 {
408 int retval;
409
410 /* We can't poll until after examine */
411 if (!target_was_examined(target))
412 {
413 LOG_ERROR("Target not examined yet");
414 return ERROR_FAIL;
415 }
416
417 /* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can
418 * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?)
419 * the application.
420 */
421 if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
422 return retval;
423
424 return retval;
425 }
426
427 int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
428 {
429 char buf[100];
430 int retval;
431 Jim_Nvp *n;
432 n = Jim_Nvp_value2name_simple( nvp_reset_modes, reset_mode );
433 if( n->name == NULL ){
434 LOG_ERROR("invalid reset mode");
435 return ERROR_FAIL;
436 }
437
438 sprintf( buf, "ocd_process_reset %s", n->name );
439 retval = Jim_Eval( interp, buf );
440
441 if(retval != JIM_OK) {
442 Jim_PrintErrorMessage(interp);
443 return ERROR_FAIL;
444 }
445
446 /* We want any events to be processed before the prompt */
447 retval = target_call_timer_callbacks_now();
448
449 return retval;
450 }
451
452 static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
453 {
454 *physical = virtual;
455 return ERROR_OK;
456 }
457
458 static int default_mmu(struct target_s *target, int *enabled)
459 {
460 *enabled = 0;
461 return ERROR_OK;
462 }
463
464 static int default_examine(struct target_s *target)
465 {
466 target_set_examined(target);
467 return ERROR_OK;
468 }
469
470 /* Targets that correctly implement init+examine, i.e.
471 * no communication with target during init:
472 *
473 * XScale
474 */
475 int target_examine(void)
476 {
477 int retval = ERROR_OK;
478 target_t *target = all_targets;
479 while (target)
480 {
481 if ((retval = target->type->examine(target))!=ERROR_OK)
482 return retval;
483 target = target->next;
484 }
485 return retval;
486 }
487
488 static int target_write_memory_imp(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
489 {
490 if (!target_was_examined(target))
491 {
492 LOG_ERROR("Target not examined yet");
493 return ERROR_FAIL;
494 }
495 return target->type->write_memory_imp(target, address, size, count, buffer);
496 }
497
498 static int target_read_memory_imp(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
499 {
500 if (!target_was_examined(target))
501 {
502 LOG_ERROR("Target not examined yet");
503 return ERROR_FAIL;
504 }
505 return target->type->read_memory_imp(target, address, size, count, buffer);
506 }
507
508 static int target_soft_reset_halt_imp(struct target_s *target)
509 {
510 if (!target_was_examined(target))
511 {
512 LOG_ERROR("Target not examined yet");
513 return ERROR_FAIL;
514 }
515 return target->type->soft_reset_halt_imp(target);
516 }
517
518 static int target_run_algorithm_imp(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
519 {
520 if (!target_was_examined(target))
521 {
522 LOG_ERROR("Target not examined yet");
523 return ERROR_FAIL;
524 }
525 return target->type->run_algorithm_imp(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info);
526 }
527
528 int target_read_memory(struct target_s *target,
529 u32 address, u32 size, u32 count, u8 *buffer)
530 {
531 return target->type->read_memory(target, address, size, count, buffer);
532 }
533
534 int target_write_memory(struct target_s *target,
535 u32 address, u32 size, u32 count, u8 *buffer)
536 {
537 return target->type->write_memory(target, address, size, count, buffer);
538 }
539
540 int target_run_algorithm(struct target_s *target,
541 int num_mem_params, mem_param_t *mem_params,
542 int num_reg_params, reg_param_t *reg_param,
543 u32 entry_point, u32 exit_point,
544 int timeout_ms, void *arch_info)
545 {
546 return target->type->run_algorithm(target,
547 num_mem_params, mem_params, num_reg_params, reg_param,
548 entry_point, exit_point, timeout_ms, arch_info);
549 }
550
551 /// @returns @c true if the target has been examined.
552 bool target_was_examined(struct target_s *target)
553 {
554 return target->type->examined;
555 }
556 /// Sets the @c examined flag for the given target.
557 void target_set_examined(struct target_s *target)
558 {
559 target->type->examined = true;
560 }
561 // Reset the @c examined flag for the given target.
562 void target_reset_examined(struct target_s *target)
563 {
564 target->type->examined = false;
565 }
566
567
568 int target_init(struct command_context_s *cmd_ctx)
569 {
570 target_t *target = all_targets;
571 int retval;
572
573 while (target)
574 {
575 target_reset_examined(target);
576 if (target->type->examine == NULL)
577 {
578 target->type->examine = default_examine;
579 }
580
581 if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
582 {
583 LOG_ERROR("target '%s' init failed", target->type->name);
584 return retval;
585 }
586
587 /* Set up default functions if none are provided by target */
588 if (target->type->virt2phys == NULL)
589 {
590 target->type->virt2phys = default_virt2phys;
591 }
592 target->type->virt2phys = default_virt2phys;
593 /* a non-invasive way(in terms of patches) to add some code that
594 * runs before the type->write/read_memory implementation
595 */
596 target->type->write_memory_imp = target->type->write_memory;
597 target->type->write_memory = target_write_memory_imp;
598 target->type->read_memory_imp = target->type->read_memory;
599 target->type->read_memory = target_read_memory_imp;
600 target->type->soft_reset_halt_imp = target->type->soft_reset_halt;
601 target->type->soft_reset_halt = target_soft_reset_halt_imp;
602 target->type->run_algorithm_imp = target->type->run_algorithm;
603 target->type->run_algorithm = target_run_algorithm_imp;
604
605 if (target->type->mmu == NULL)
606 {
607 target->type->mmu = default_mmu;
608 }
609 target = target->next;
610 }
611
612 if (all_targets)
613 {
614 if((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK)
615 return retval;
616 if((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK)
617 return retval;
618 }
619
620 return ERROR_OK;
621 }
622
623 int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
624 {
625 target_event_callback_t **callbacks_p = &target_event_callbacks;
626
627 if (callback == NULL)
628 {
629 return ERROR_INVALID_ARGUMENTS;
630 }
631
632 if (*callbacks_p)
633 {
634 while ((*callbacks_p)->next)
635 callbacks_p = &((*callbacks_p)->next);
636 callbacks_p = &((*callbacks_p)->next);
637 }
638
639 (*callbacks_p) = malloc(sizeof(target_event_callback_t));
640 (*callbacks_p)->callback = callback;
641 (*callbacks_p)->priv = priv;
642 (*callbacks_p)->next = NULL;
643
644 return ERROR_OK;
645 }
646
647 int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
648 {
649 target_timer_callback_t **callbacks_p = &target_timer_callbacks;
650 struct timeval now;
651
652 if (callback == NULL)
653 {
654 return ERROR_INVALID_ARGUMENTS;
655 }
656
657 if (*callbacks_p)
658 {
659 while ((*callbacks_p)->next)
660 callbacks_p = &((*callbacks_p)->next);
661 callbacks_p = &((*callbacks_p)->next);
662 }
663
664 (*callbacks_p) = malloc(sizeof(target_timer_callback_t));
665 (*callbacks_p)->callback = callback;
666 (*callbacks_p)->periodic = periodic;
667 (*callbacks_p)->time_ms = time_ms;
668
669 gettimeofday(&now, NULL);
670 (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
671 time_ms -= (time_ms % 1000);
672 (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
673 if ((*callbacks_p)->when.tv_usec > 1000000)
674 {
675 (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
676 (*callbacks_p)->when.tv_sec += 1;
677 }
678
679 (*callbacks_p)->priv = priv;
680 (*callbacks_p)->next = NULL;
681
682 return ERROR_OK;
683 }
684
685 int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
686 {
687 target_event_callback_t **p = &target_event_callbacks;
688 target_event_callback_t *c = target_event_callbacks;
689
690 if (callback == NULL)
691 {
692 return ERROR_INVALID_ARGUMENTS;
693 }
694
695 while (c)
696 {
697 target_event_callback_t *next = c->next;
698 if ((c->callback == callback) && (c->priv == priv))
699 {
700 *p = next;
701 free(c);
702 return ERROR_OK;
703 }
704 else
705 p = &(c->next);
706 c = next;
707 }
708
709 return ERROR_OK;
710 }
711
712 int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
713 {
714 target_timer_callback_t **p = &target_timer_callbacks;
715 target_timer_callback_t *c = target_timer_callbacks;
716
717 if (callback == NULL)
718 {
719 return ERROR_INVALID_ARGUMENTS;
720 }
721
722 while (c)
723 {
724 target_timer_callback_t *next = c->next;
725 if ((c->callback == callback) && (c->priv == priv))
726 {
727 *p = next;
728 free(c);
729 return ERROR_OK;
730 }
731 else
732 p = &(c->next);
733 c = next;
734 }
735
736 return ERROR_OK;
737 }
738
739 int target_call_event_callbacks(target_t *target, enum target_event event)
740 {
741 target_event_callback_t *callback = target_event_callbacks;
742 target_event_callback_t *next_callback;
743
744 if (event == TARGET_EVENT_HALTED)
745 {
746 /* execute early halted first */
747 target_call_event_callbacks(target, TARGET_EVENT_EARLY_HALTED);
748 }
749
750 LOG_DEBUG("target event %i (%s)",
751 event,
752 Jim_Nvp_value2name_simple( nvp_target_event, event )->name );
753
754 target_handle_event( target, event );
755
756 while (callback)
757 {
758 next_callback = callback->next;
759 callback->callback(target, event, callback->priv);
760 callback = next_callback;
761 }
762
763 return ERROR_OK;
764 }
765
766 static int target_call_timer_callbacks_check_time(int checktime)
767 {
768 target_timer_callback_t *callback = target_timer_callbacks;
769 target_timer_callback_t *next_callback;
770 struct timeval now;
771
772 keep_alive();
773
774 gettimeofday(&now, NULL);
775
776 while (callback)
777 {
778 next_callback = callback->next;
779
780 if ((!checktime&&callback->periodic)||
781 (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec))
782 || (now.tv_sec > callback->when.tv_sec)))
783 {
784 if(callback->callback != NULL)
785 {
786 callback->callback(callback->priv);
787 if (callback->periodic)
788 {
789 int time_ms = callback->time_ms;
790 callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
791 time_ms -= (time_ms % 1000);
792 callback->when.tv_sec = now.tv_sec + time_ms / 1000;
793 if (callback->when.tv_usec > 1000000)
794 {
795 callback->when.tv_usec = callback->when.tv_usec - 1000000;
796 callback->when.tv_sec += 1;
797 }
798 }
799 else
800 {
801 int retval;
802 if((retval = target_unregister_timer_callback(callback->callback, callback->priv)) != ERROR_OK)
803 return retval;
804 }
805 }
806 }
807
808 callback = next_callback;
809 }
810
811 return ERROR_OK;
812 }
813
814 int target_call_timer_callbacks(void)
815 {
816 return target_call_timer_callbacks_check_time(1);
817 }
818
819 /* invoke periodic callbacks immediately */
820 int target_call_timer_callbacks_now(void)
821 {
822 return target_call_timer_callbacks_check_time(0);
823 }
824
825 int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)
826 {
827 working_area_t *c = target->working_areas;
828 working_area_t *new_wa = NULL;
829
830 /* Reevaluate working area address based on MMU state*/
831 if (target->working_areas == NULL)
832 {
833 int retval;
834 int enabled;
835 retval = target->type->mmu(target, &enabled);
836 if (retval != ERROR_OK)
837 {
838 return retval;
839 }
840 if (enabled)
841 {
842 target->working_area = target->working_area_virt;
843 }
844 else
845 {
846 target->working_area = target->working_area_phys;
847 }
848 }
849
850 /* only allocate multiples of 4 byte */
851 if (size % 4)
852 {
853 LOG_ERROR("BUG: code tried to allocate unaligned number of bytes, padding");
854 size = CEIL(size, 4);
855 }
856
857 /* see if there's already a matching working area */
858 while (c)
859 {
860 if ((c->free) && (c->size == size))
861 {
862 new_wa = c;
863 break;
864 }
865 c = c->next;
866 }
867
868 /* if not, allocate a new one */
869 if (!new_wa)
870 {
871 working_area_t **p = &target->working_areas;
872 u32 first_free = target->working_area;
873 u32 free_size = target->working_area_size;
874
875 LOG_DEBUG("allocating new working area");
876
877 c = target->working_areas;
878 while (c)
879 {
880 first_free += c->size;
881 free_size -= c->size;
882 p = &c->next;
883 c = c->next;
884 }
885
886 if (free_size < size)
887 {
888 LOG_WARNING("not enough working area available(requested %d, free %d)", size, free_size);
889 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
890 }
891
892 new_wa = malloc(sizeof(working_area_t));
893 new_wa->next = NULL;
894 new_wa->size = size;
895 new_wa->address = first_free;
896
897 if (target->backup_working_area)
898 {
899 int retval;
900 new_wa->backup = malloc(new_wa->size);
901 if((retval = target_read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup)) != ERROR_OK)
902 {
903 free(new_wa->backup);
904 free(new_wa);
905 return retval;
906 }
907 }
908 else
909 {
910 new_wa->backup = NULL;
911 }
912
913 /* put new entry in list */
914 *p = new_wa;
915 }
916
917 /* mark as used, and return the new (reused) area */
918 new_wa->free = 0;
919 *area = new_wa;
920
921 /* user pointer */
922 new_wa->user = area;
923
924 return ERROR_OK;
925 }
926
927 int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore)
928 {
929 if (area->free)
930 return ERROR_OK;
931
932 if (restore&&target->backup_working_area)
933 {
934 int retval;
935 if((retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup)) != ERROR_OK)
936 return retval;
937 }
938
939 area->free = 1;
940
941 /* mark user pointer invalid */
942 *area->user = NULL;
943 area->user = NULL;
944
945 return ERROR_OK;
946 }
947
948 int target_free_working_area(struct target_s *target, working_area_t *area)
949 {
950 return target_free_working_area_restore(target, area, 1);
951 }
952
953 /* free resources and restore memory, if restoring memory fails,
954 * free up resources anyway
955 */
956 void target_free_all_working_areas_restore(struct target_s *target, int restore)
957 {
958 working_area_t *c = target->working_areas;
959
960 while (c)
961 {
962 working_area_t *next = c->next;
963 target_free_working_area_restore(target, c, restore);
964
965 if (c->backup)
966 free(c->backup);
967
968 free(c);
969
970 c = next;
971 }
972
973 target->working_areas = NULL;
974 }
975
976 void target_free_all_working_areas(struct target_s *target)
977 {
978 target_free_all_working_areas_restore(target, 1);
979 }
980
981 int target_register_commands(struct command_context_s *cmd_ctx)
982 {
983
984 register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, "change the current command line target (one parameter) or lists targets (with no parameter)");
985
986
987
988
989 register_jim(cmd_ctx, "target", jim_target, "configure target" );
990
991 return ERROR_OK;
992 }
993
994 int target_arch_state(struct target_s *target)
995 {
996 int retval;
997 if (target==NULL)
998 {
999 LOG_USER("No target has been configured");
1000 return ERROR_OK;
1001 }
1002
1003 LOG_USER("target state: %s",
1004 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
1005
1006 if (target->state!=TARGET_HALTED)
1007 return ERROR_OK;
1008
1009 retval=target->type->arch_state(target);
1010 return retval;
1011 }
1012
1013 /* Single aligned words are guaranteed to use 16 or 32 bit access
1014 * mode respectively, otherwise data is handled as quickly as
1015 * possible
1016 */
1017 int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
1018 {
1019 int retval;
1020 LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);
1021
1022 if (!target_was_examined(target))
1023 {
1024 LOG_ERROR("Target not examined yet");
1025 return ERROR_FAIL;
1026 }
1027
1028 if (size == 0) {
1029 return ERROR_OK;
1030 }
1031
1032 if ((address + size - 1) < address)
1033 {
1034 /* GDB can request this when e.g. PC is 0xfffffffc*/
1035 LOG_ERROR("address+size wrapped(0x%08x, 0x%08x)", address, size);
1036 return ERROR_FAIL;
1037 }
1038
1039 if (((address % 2) == 0) && (size == 2))
1040 {
1041 return target_write_memory(target, address, 2, 1, buffer);
1042 }
1043
1044 /* handle unaligned head bytes */
1045 if (address % 4)
1046 {
1047 u32 unaligned = 4 - (address % 4);
1048
1049 if (unaligned > size)
1050 unaligned = size;
1051
1052 if ((retval = target_write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
1053 return retval;
1054
1055 buffer += unaligned;
1056 address += unaligned;
1057 size -= unaligned;
1058 }
1059
1060 /* handle aligned words */
1061 if (size >= 4)
1062 {
1063 int aligned = size - (size % 4);
1064
1065 /* use bulk writes above a certain limit. This may have to be changed */
1066 if (aligned > 128)
1067 {
1068 if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)
1069 return retval;
1070 }
1071 else
1072 {
1073 if ((retval = target_write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
1074 return retval;
1075 }
1076
1077 buffer += aligned;
1078 address += aligned;
1079 size -= aligned;
1080 }
1081
1082 /* handle tail writes of less than 4 bytes */
1083 if (size > 0)
1084 {
1085 if ((retval = target_write_memory(target, address, 1, size, buffer)) != ERROR_OK)
1086 return retval;
1087 }
1088
1089 return ERROR_OK;
1090 }
1091
1092 /* Single aligned words are guaranteed to use 16 or 32 bit access
1093 * mode respectively, otherwise data is handled as quickly as
1094 * possible
1095 */
1096 int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
1097 {
1098 int retval;
1099 LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);
1100
1101 if (!target_was_examined(target))
1102 {
1103 LOG_ERROR("Target not examined yet");
1104 return ERROR_FAIL;
1105 }
1106
1107 if (size == 0) {
1108 return ERROR_OK;
1109 }
1110
1111 if ((address + size - 1) < address)
1112 {
1113 /* GDB can request this when e.g. PC is 0xfffffffc*/
1114 LOG_ERROR("address+size wrapped(0x%08x, 0x%08x)", address, size);
1115 return ERROR_FAIL;
1116 }
1117
1118 if (((address % 2) == 0) && (size == 2))
1119 {
1120 return target_read_memory(target, address, 2, 1, buffer);
1121 }
1122
1123 /* handle unaligned head bytes */
1124 if (address % 4)
1125 {
1126 u32 unaligned = 4 - (address % 4);
1127
1128 if (unaligned > size)
1129 unaligned = size;
1130
1131 if ((retval = target_read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
1132 return retval;
1133
1134 buffer += unaligned;
1135 address += unaligned;
1136 size -= unaligned;
1137 }
1138
1139 /* handle aligned words */
1140 if (size >= 4)
1141 {
1142 int aligned = size - (size % 4);
1143
1144 if ((retval = target_read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
1145 return retval;
1146
1147 buffer += aligned;
1148 address += aligned;
1149 size -= aligned;
1150 }
1151
1152 /* handle tail writes of less than 4 bytes */
1153 if (size > 0)
1154 {
1155 if ((retval = target_read_memory(target, address, 1, size, buffer)) != ERROR_OK)
1156 return retval;
1157 }
1158
1159 return ERROR_OK;
1160 }
1161
1162 int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
1163 {
1164 u8 *buffer;
1165 int retval;
1166 u32 i;
1167 u32 checksum = 0;
1168 if (!target_was_examined(target))
1169 {
1170 LOG_ERROR("Target not examined yet");
1171 return ERROR_FAIL;
1172 }
1173
1174 if ((retval = target->type->checksum_memory(target, address,
1175 size, &checksum)) != ERROR_OK)
1176 {
1177 buffer = malloc(size);
1178 if (buffer == NULL)
1179 {
1180 LOG_ERROR("error allocating buffer for section (%d bytes)", size);
1181 return ERROR_INVALID_ARGUMENTS;
1182 }
1183 retval = target_read_buffer(target, address, size, buffer);
1184 if (retval != ERROR_OK)
1185 {
1186 free(buffer);
1187 return retval;
1188 }
1189
1190 /* convert to target endianess */
1191 for (i = 0; i < (size/sizeof(u32)); i++)
1192 {
1193 u32 target_data;
1194 target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);
1195 target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);
1196 }
1197
1198 retval = image_calculate_checksum( buffer, size, &checksum );
1199 free(buffer);
1200 }
1201
1202 *crc = checksum;
1203
1204 return retval;
1205 }
1206
1207 int target_blank_check_memory(struct target_s *target, u32 address, u32 size, u32* blank)
1208 {
1209 int retval;
1210 if (!target_was_examined(target))
1211 {
1212 LOG_ERROR("Target not examined yet");
1213 return ERROR_FAIL;
1214 }
1215
1216 if (target->type->blank_check_memory == 0)
1217 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1218
1219 retval = target->type->blank_check_memory(target, address, size, blank);
1220
1221 return retval;
1222 }
1223
1224 int target_read_u32(struct target_s *target, u32 address, u32 *value)
1225 {
1226 u8 value_buf[4];
1227 if (!target_was_examined(target))
1228 {
1229 LOG_ERROR("Target not examined yet");
1230 return ERROR_FAIL;
1231 }
1232
1233 int retval = target_read_memory(target, address, 4, 1, value_buf);
1234
1235 if (retval == ERROR_OK)
1236 {
1237 *value = target_buffer_get_u32(target, value_buf);
1238 LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
1239 }
1240 else
1241 {
1242 *value = 0x0;
1243 LOG_DEBUG("address: 0x%8.8x failed", address);
1244 }
1245
1246 return retval;
1247 }
1248
1249 int target_read_u16(struct target_s *target, u32 address, u16 *value)
1250 {
1251 u8 value_buf[2];
1252 if (!target_was_examined(target))
1253 {
1254 LOG_ERROR("Target not examined yet");
1255 return ERROR_FAIL;
1256 }
1257
1258 int retval = target_read_memory(target, address, 2, 1, value_buf);
1259
1260 if (retval == ERROR_OK)
1261 {
1262 *value = target_buffer_get_u16(target, value_buf);
1263 LOG_DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
1264 }
1265 else
1266 {
1267 *value = 0x0;
1268 LOG_DEBUG("address: 0x%8.8x failed", address);
1269 }
1270
1271 return retval;
1272 }
1273
1274 int target_read_u8(struct target_s *target, u32 address, u8 *value)
1275 {
1276 int retval = target_read_memory(target, address, 1, 1, value);
1277 if (!target_was_examined(target))
1278 {
1279 LOG_ERROR("Target not examined yet");
1280 return ERROR_FAIL;
1281 }
1282
1283 if (retval == ERROR_OK)
1284 {
1285 LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
1286 }
1287 else
1288 {
1289 *value = 0x0;
1290 LOG_DEBUG("address: 0x%8.8x failed", address);
1291 }
1292
1293 return retval;
1294 }
1295
1296 int target_write_u32(struct target_s *target, u32 address, u32 value)
1297 {
1298 int retval;
1299 u8 value_buf[4];
1300 if (!target_was_examined(target))
1301 {
1302 LOG_ERROR("Target not examined yet");
1303 return ERROR_FAIL;
1304 }
1305
1306 LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
1307
1308 target_buffer_set_u32(target, value_buf, value);
1309 if ((retval = target_write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
1310 {
1311 LOG_DEBUG("failed: %i", retval);
1312 }
1313
1314 return retval;
1315 }
1316
1317 int target_write_u16(struct target_s *target, u32 address, u16 value)
1318 {
1319 int retval;
1320 u8 value_buf[2];
1321 if (!target_was_examined(target))
1322 {
1323 LOG_ERROR("Target not examined yet");
1324 return ERROR_FAIL;
1325 }
1326
1327 LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
1328
1329 target_buffer_set_u16(target, value_buf, value);
1330 if ((retval = target_write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
1331 {
1332 LOG_DEBUG("failed: %i", retval);
1333 }
1334
1335 return retval;
1336 }
1337
1338 int target_write_u8(struct target_s *target, u32 address, u8 value)
1339 {
1340 int retval;
1341 if (!target_was_examined(target))
1342 {
1343 LOG_ERROR("Target not examined yet");
1344 return ERROR_FAIL;
1345 }
1346
1347 LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
1348
1349 if ((retval = target_write_memory(target, address, 1, 1, &value)) != ERROR_OK)
1350 {
1351 LOG_DEBUG("failed: %i", retval);
1352 }
1353
1354 return retval;
1355 }
1356
1357 int target_register_user_commands(struct command_context_s *cmd_ctx)
1358 {
1359 int retval = ERROR_OK;
1360
1361
1362 /* script procedures */
1363 register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "profiling samples the CPU PC");
1364 register_jim(cmd_ctx, "ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing <ARRAYNAME> <WIDTH=32/16/8> <ADDRESS> <COUNT>");
1365 register_jim(cmd_ctx, "ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values <ARRAYNAME> <WIDTH=32/16/8> <ADDRESS> <COUNT>");
1366
1367 register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,
1368 "same args as load_image, image stored in memory - mainly for profiling purposes");
1369
1370 register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,
1371 "loads active fast load image to current target - mainly for profiling purposes");
1372
1373
1374 register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "translate a virtual address into a physical address");
1375 register_command(cmd_ctx, NULL, "reg", handle_reg_command, COMMAND_EXEC, "display or set a register");
1376 register_command(cmd_ctx, NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");
1377 register_command(cmd_ctx, NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
1378 register_command(cmd_ctx, NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
1379 register_command(cmd_ctx, NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
1380 register_command(cmd_ctx, NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
1381 register_command(cmd_ctx, NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init] - default is run");
1382 register_command(cmd_ctx, NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
1383
1384 register_command(cmd_ctx, NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
1385 register_command(cmd_ctx, NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
1386 register_command(cmd_ctx, NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
1387
1388 register_command(cmd_ctx, NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value> [count]");
1389 register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value> [count]");
1390 register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value> [count]");
1391
1392 register_command(cmd_ctx, NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");
1393 register_command(cmd_ctx, NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");
1394 register_command(cmd_ctx, NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");
1395 register_command(cmd_ctx, NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
1396
1397 register_command(cmd_ctx, NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19'] [min_address] [max_length]");
1398 register_command(cmd_ctx, NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
1399 register_command(cmd_ctx, NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");
1400 register_command(cmd_ctx, NULL, "test_image", handle_test_image_command, COMMAND_EXEC, "test_image <file> [offset] [type]");
1401
1402 if((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK)
1403 return retval;
1404 if((retval = trace_register_commands(cmd_ctx)) != ERROR_OK)
1405 return retval;
1406
1407 return retval;
1408 }
1409
1410 static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1411 {
1412 target_t *target = all_targets;
1413
1414 if (argc == 1)
1415 {
1416 target = get_target(args[0]);
1417 if (target == NULL) {
1418 command_print(cmd_ctx,"Target: %s is unknown, try one of:\n", args[0] );
1419 goto DumpTargets;
1420 }
1421
1422 cmd_ctx->current_target = target->target_number;
1423 return ERROR_OK;
1424 }
1425 DumpTargets:
1426
1427 target = all_targets;
1428 command_print(cmd_ctx, " CmdName Type Endian AbsChainPos Name State ");
1429 command_print(cmd_ctx, "-- ---------- ---------- ---------- ----------- ------------- ----------");
1430 while (target)
1431 {
1432 /* XX: abcdefghij abcdefghij abcdefghij abcdefghij */
1433 command_print(cmd_ctx, "%2d: %-10s %-10s %-10s %10d %14s %s",
1434 target->target_number,
1435 target->cmd_name,
1436 target->type->name,
1437 Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness )->name,
1438 target->tap->abs_chain_position,
1439 target->tap->dotted_name,
1440 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
1441 target = target->next;
1442 }
1443
1444 return ERROR_OK;
1445 }
1446
1447 /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */
1448
1449 static int powerDropout;
1450 static int srstAsserted;
1451
1452 static int runPowerRestore;
1453 static int runPowerDropout;
1454 static int runSrstAsserted;
1455 static int runSrstDeasserted;
1456
1457 static int sense_handler(void)
1458 {
1459 static int prevSrstAsserted = 0;
1460 static int prevPowerdropout = 0;
1461
1462 int retval;
1463 if ((retval=jtag_power_dropout(&powerDropout))!=ERROR_OK)
1464 return retval;
1465
1466 int powerRestored;
1467 powerRestored = prevPowerdropout && !powerDropout;
1468 if (powerRestored)
1469 {
1470 runPowerRestore = 1;
1471 }
1472
1473 long long current = timeval_ms();
1474 static long long lastPower = 0;
1475 int waitMore = lastPower + 2000 > current;
1476 if (powerDropout && !waitMore)
1477 {
1478 runPowerDropout = 1;
1479 lastPower = current;
1480 }
1481
1482 if ((retval=jtag_srst_asserted(&srstAsserted))!=ERROR_OK)
1483 return retval;
1484
1485 int srstDeasserted;
1486 srstDeasserted = prevSrstAsserted && !srstAsserted;
1487
1488 static long long lastSrst = 0;
1489 waitMore = lastSrst + 2000 > current;
1490 if (srstDeasserted && !waitMore)
1491 {
1492 runSrstDeasserted = 1;
1493 lastSrst = current;
1494 }
1495
1496 if (!prevSrstAsserted && srstAsserted)
1497 {
1498 runSrstAsserted = 1;
1499 }
1500
1501 prevSrstAsserted = srstAsserted;
1502 prevPowerdropout = powerDropout;
1503
1504 if (srstDeasserted || powerRestored)
1505 {
1506 /* Other than logging the event we can't do anything here.
1507 * Issuing a reset is a particularly bad idea as we might
1508 * be inside a reset already.
1509 */
1510 }
1511
1512 return ERROR_OK;
1513 }
1514
1515 /* process target state changes */
1516 int handle_target(void *priv)
1517 {
1518 int retval = ERROR_OK;
1519
1520 /* we do not want to recurse here... */
1521 static int recursive = 0;
1522 if (! recursive)
1523 {
1524 recursive = 1;
1525 sense_handler();
1526 /* danger! running these procedures can trigger srst assertions and power dropouts.
1527 * We need to avoid an infinite loop/recursion here and we do that by
1528 * clearing the flags after running these events.
1529 */
1530 int did_something = 0;
1531 if (runSrstAsserted)
1532 {
1533 Jim_Eval( interp, "srst_asserted");
1534 did_something = 1;
1535 }
1536 if (runSrstDeasserted)
1537 {
1538 Jim_Eval( interp, "srst_deasserted");
1539 did_something = 1;
1540 }
1541 if (runPowerDropout)
1542 {
1543 Jim_Eval( interp, "power_dropout");
1544 did_something = 1;
1545 }
1546 if (runPowerRestore)
1547 {
1548 Jim_Eval( interp, "power_restore");
1549 did_something = 1;
1550 }
1551
1552 if (did_something)
1553 {
1554 /* clear detect flags */
1555 sense_handler();
1556 }
1557
1558 /* clear action flags */
1559
1560 runSrstAsserted=0;
1561 runSrstDeasserted=0;
1562 runPowerRestore=0;
1563 runPowerDropout=0;
1564
1565 recursive = 0;
1566 }
1567
1568 target_t *target = all_targets;
1569
1570 while (target)
1571 {
1572
1573 /* only poll target if we've got power and srst isn't asserted */
1574 if (target_continous_poll&&!powerDropout&&!srstAsserted)
1575 {
1576 /* polling may fail silently until the target has been examined */
1577 if((retval = target_poll(target)) != ERROR_OK)
1578 return retval;
1579 }
1580
1581 target = target->next;
1582 }
1583
1584 return retval;
1585 }
1586
1587 static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1588 {
1589 target_t *target;
1590 reg_t *reg = NULL;
1591 int count = 0;
1592 char *value;
1593
1594 LOG_DEBUG("-");
1595
1596 target = get_current_target(cmd_ctx);
1597
1598 /* list all available registers for the current target */
1599 if (argc == 0)
1600 {
1601 reg_cache_t *cache = target->reg_cache;
1602
1603 count = 0;
1604 while(cache)
1605 {
1606 int i;
1607 for (i = 0; i < cache->num_regs; i++)
1608 {
1609 value = buf_to_str(cache->reg_list[i].value, cache->reg_list[i].size, 16);
1610 command_print(cmd_ctx, "(%i) %s (/%i): 0x%s (dirty: %i, valid: %i)", count++, cache->reg_list[i].name, cache->reg_list[i].size, value, cache->reg_list[i].dirty, cache->reg_list[i].valid);
1611 free(value);
1612 }
1613 cache = cache->next;
1614 }
1615
1616 return ERROR_OK;
1617 }
1618
1619 /* access a single register by its ordinal number */
1620 if ((args[0][0] >= '0') && (args[0][0] <= '9'))
1621 {
1622 int num = strtoul(args[0], NULL, 0);
1623 reg_cache_t *cache = target->reg_cache;
1624
1625 count = 0;
1626 while(cache)
1627 {
1628 int i;
1629 for (i = 0; i < cache->num_regs; i++)
1630 {
1631 if (count++ == num)
1632 {
1633 reg = &cache->reg_list[i];
1634 break;
1635 }
1636 }
1637 if (reg)
1638 break;
1639 cache = cache->next;
1640 }
1641
1642 if (!reg)
1643 {
1644 command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
1645 return ERROR_OK;
1646 }
1647 } else /* access a single register by its name */
1648 {
1649 reg = register_get_by_name(target->reg_cache, args[0], 1);
1650
1651 if (!reg)
1652 {
1653 command_print(cmd_ctx, "register %s not found in current target", args[0]);
1654 return ERROR_OK;
1655 }
1656 }
1657
1658 /* display a register */
1659 if ((argc == 1) || ((argc == 2) && !((args[1][0] >= '0') && (args[1][0] <= '9'))))
1660 {
1661 if ((argc == 2) && (strcmp(args[1], "force") == 0))
1662 reg->valid = 0;
1663
1664 if (reg->valid == 0)
1665 {
1666 reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
1667 arch_type->get(reg);
1668 }
1669 value = buf_to_str(reg->value, reg->size, 16);
1670 command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
1671 free(value);
1672 return ERROR_OK;
1673 }
1674
1675 /* set register value */
1676 if (argc == 2)
1677 {
1678 u8 *buf = malloc(CEIL(reg->size, 8));
1679 str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);
1680
1681 reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
1682 arch_type->set(reg, buf);
1683
1684 value = buf_to_str(reg->value, reg->size, 16);
1685 command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
1686 free(value);
1687
1688 free(buf);
1689
1690 return ERROR_OK;
1691 }
1692
1693 command_print(cmd_ctx, "usage: reg <#|name> [value]");
1694
1695 return ERROR_OK;
1696 }
1697
1698 static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1699 {
1700 int retval = ERROR_OK;
1701 target_t *target = get_current_target(cmd_ctx);
1702
1703 if (argc == 0)
1704 {
1705 if((retval = target_poll(target)) != ERROR_OK)
1706 return retval;
1707 if((retval = target_arch_state(target)) != ERROR_OK)
1708 return retval;
1709
1710 }
1711 else if (argc==1)
1712 {
1713 if (strcmp(args[0], "on") == 0)
1714 {
1715 target_continous_poll = 1;
1716 }
1717 else if (strcmp(args[0], "off") == 0)
1718 {
1719 target_continous_poll = 0;
1720 }
1721 else
1722 {
1723 command_print(cmd_ctx, "arg is \"on\" or \"off\"");
1724 }
1725 } else
1726 {
1727 return ERROR_COMMAND_SYNTAX_ERROR;
1728 }
1729
1730 return retval;
1731 }
1732
1733 static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1734 {
1735 int ms = 5000;
1736
1737 if (argc > 0)
1738 {
1739 char *end;
1740
1741 ms = strtoul(args[0], &end, 0) * 1000;
1742 if (*end)
1743 {
1744 command_print(cmd_ctx, "usage: %s [seconds]", cmd);
1745 return ERROR_OK;
1746 }
1747 }
1748 target_t *target = get_current_target(cmd_ctx);
1749
1750 return target_wait_state(target, TARGET_HALTED, ms);
1751 }
1752
1753 /* wait for target state to change. The trick here is to have a low
1754 * latency for short waits and not to suck up all the CPU time
1755 * on longer waits.
1756 *
1757 * After 500ms, keep_alive() is invoked
1758 */
1759 int target_wait_state(target_t *target, enum target_state state, int ms)
1760 {
1761 int retval;
1762 long long then=0, cur;
1763 int once=1;
1764
1765 for (;;)
1766 {
1767 if ((retval=target_poll(target))!=ERROR_OK)
1768 return retval;
1769 if (target->state == state)
1770 {
1771 break;
1772 }
1773 cur = timeval_ms();
1774 if (once)
1775 {
1776 once=0;
1777 then = timeval_ms();
1778 LOG_DEBUG("waiting for target %s...",
1779 Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
1780 }
1781
1782 if (cur-then>500)
1783 {
1784 keep_alive();
1785 }
1786
1787 if ((cur-then)>ms)
1788 {
1789 LOG_ERROR("timed out while waiting for target %s",
1790 Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
1791 return ERROR_FAIL;
1792 }
1793 }
1794
1795 return ERROR_OK;
1796 }
1797
1798 static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1799 {
1800 int retval;
1801 target_t *target = get_current_target(cmd_ctx);
1802
1803 LOG_DEBUG("-");
1804
1805 if ((retval = target_halt(target)) != ERROR_OK)
1806 {
1807 return retval;
1808 }
1809
1810 if (argc == 1)
1811 {
1812 int wait;
1813 char *end;
1814
1815 wait = strtoul(args[0], &end, 0);
1816 if (!*end && !wait)
1817 return ERROR_OK;
1818 }
1819
1820 return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
1821 }
1822
1823 static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1824 {
1825 target_t *target = get_current_target(cmd_ctx);
1826
1827 LOG_USER("requesting target halt and executing a soft reset");
1828
1829 target->type->soft_reset_halt(target);
1830
1831 return ERROR_OK;
1832 }
1833
1834 static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1835 {
1836 const Jim_Nvp *n;
1837 enum target_reset_mode reset_mode = RESET_RUN;
1838
1839 if (argc >= 1)
1840 {
1841 n = Jim_Nvp_name2value_simple( nvp_reset_modes, args[0] );
1842 if( (n->name == NULL) || (n->value == RESET_UNKNOWN) ){
1843 return ERROR_COMMAND_SYNTAX_ERROR;
1844 }
1845 reset_mode = n->value;
1846 }
1847
1848 /* reset *all* targets */
1849 return target_process_reset(cmd_ctx, reset_mode);
1850 }
1851
1852
1853 static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1854 {
1855 int retval;
1856 target_t *target = get_current_target(cmd_ctx);
1857
1858 target_handle_event( target, TARGET_EVENT_OLD_pre_resume );
1859
1860 if (argc == 0)
1861 retval = target_resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */
1862 else if (argc == 1)
1863 retval = target_resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */
1864 else
1865 {
1866 retval = ERROR_COMMAND_SYNTAX_ERROR;
1867 }
1868
1869 return retval;
1870 }
1871
1872 static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1873 {
1874 target_t *target = get_current_target(cmd_ctx);
1875
1876 LOG_DEBUG("-");
1877
1878 if (argc == 0)
1879 return target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
1880
1881 if (argc == 1)
1882 return target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
1883
1884 return ERROR_OK;
1885 }
1886
1887 static void handle_md_output(struct command_context_s *cmd_ctx,
1888 struct target_s *target, u32 address, unsigned size,
1889 unsigned count, const u8 *buffer)
1890 {
1891 const unsigned line_bytecnt = 32;
1892 unsigned line_modulo = line_bytecnt / size;
1893
1894 char output[line_bytecnt * 4 + 1];
1895 unsigned output_len = 0;
1896
1897 const char *value_fmt;
1898 switch (size) {
1899 case 4: value_fmt = "%8.8x"; break;
1900 case 2: value_fmt = "%4.2x"; break;
1901 case 1: value_fmt = "%2.2x"; break;
1902 default:
1903 LOG_ERROR("invalid memory read size: %u", size);
1904 exit(-1);
1905 }
1906
1907 for (unsigned i = 0; i < count; i++)
1908 {
1909 if (i % line_modulo == 0)
1910 {
1911 output_len += snprintf(output + output_len,
1912 sizeof(output) - output_len,
1913 "0x%8.8x: ", address + (i*size));
1914 }
1915
1916 u32 value;
1917 const u8 *value_ptr = buffer + i * size;
1918 switch (size) {
1919 case 4: value = target_buffer_get_u32(target, value_ptr); break;
1920 case 2: value = target_buffer_get_u16(target, value_ptr); break;
1921 case 1: value = *value_ptr;
1922 }
1923 output_len += snprintf(output + output_len,
1924 sizeof(output) - output_len,
1925 value_fmt, value);
1926
1927 if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
1928 {
1929 command_print(cmd_ctx, "%s", output);
1930 output_len = 0;
1931 }
1932 }
1933 }
1934
1935 static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1936 {
1937 if (argc < 1)
1938 return ERROR_COMMAND_SYNTAX_ERROR;
1939
1940 unsigned size = 0;
1941 switch (cmd[2]) {
1942 case 'w': size = 4; break;
1943 case 'h': size = 2; break;
1944 case 'b': size = 1; break;
1945 default: return ERROR_COMMAND_SYNTAX_ERROR;
1946 }
1947
1948 u32 address = strtoul(args[0], NULL, 0);
1949
1950 unsigned count = 1;
1951 if (argc == 2)
1952 count = strtoul(args[1], NULL, 0);
1953
1954 u8 *buffer = calloc(count, size);
1955
1956 target_t *target = get_current_target(cmd_ctx);
1957 int retval = target_read_memory(target,
1958 address, size, count, buffer);
1959 if (ERROR_OK == retval)
1960 handle_md_output(cmd_ctx, target, address, size, count, buffer);
1961
1962 free(buffer);
1963
1964 return retval;
1965 }
1966
1967 static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1968 {
1969 u32 address = 0;
1970 u32 value = 0;
1971 int count = 1;
1972 int i;
1973 int wordsize;
1974 target_t *target = get_current_target(cmd_ctx);
1975 u8 value_buf[4];
1976
1977 if ((argc < 2) || (argc > 3))
1978 return ERROR_COMMAND_SYNTAX_ERROR;
1979
1980 address = strtoul(args[0], NULL, 0);
1981 value = strtoul(args[1], NULL, 0);
1982 if (argc == 3)
1983 count = strtoul(args[2], NULL, 0);
1984
1985 switch (cmd[2])
1986 {
1987 case 'w':
1988 wordsize = 4;
1989 target_buffer_set_u32(target, value_buf, value);
1990 break;
1991 case 'h':
1992 wordsize = 2;
1993 target_buffer_set_u16(target, value_buf, value);
1994 break;
1995 case 'b':
1996 wordsize = 1;
1997 value_buf[0] = value;
1998 break;
1999 default:
2000 return ERROR_COMMAND_SYNTAX_ERROR;
2001 }
2002 for (i=0; i<count; i++)
2003 {
2004 int retval = target_write_memory(target,
2005 address + i * wordsize, wordsize, 1, value_buf);
2006 if (ERROR_OK != retval)
2007 return retval;
2008 keep_alive();
2009 }
2010
2011 return ERROR_OK;
2012
2013 }
2014
2015 static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2016 {
2017 u8 *buffer;
2018 u32 buf_cnt;
2019 u32 image_size;
2020 u32 min_address=0;
2021 u32 max_address=0xffffffff;
2022 int i;
2023 int retval, retvaltemp;
2024
2025 image_t image;
2026
2027 duration_t duration;
2028 char *duration_text;
2029
2030 target_t *target = get_current_target(cmd_ctx);
2031
2032 if ((argc < 1)||(argc > 5))
2033 {
2034 return ERROR_COMMAND_SYNTAX_ERROR;
2035 }
2036
2037 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
2038 if (argc >= 2)
2039 {
2040 image.base_address_set = 1;
2041 image.base_address = strtoul(args[1], NULL, 0);
2042 }
2043 else
2044 {
2045 image.base_address_set = 0;
2046 }
2047
2048
2049 image.start_address_set = 0;
2050
2051 if (argc>=4)
2052 {
2053 min_address=strtoul(args[3], NULL, 0);
2054 }
2055 if (argc>=5)
2056 {
2057 max_address=strtoul(args[4], NULL, 0)+min_address;
2058 }
2059
2060 if (min_address>max_address)
2061 {
2062 return ERROR_COMMAND_SYNTAX_ERROR;
2063 }
2064
2065 duration_start_measure(&duration);
2066
2067 if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
2068 {
2069 return ERROR_OK;
2070 }
2071
2072 image_size = 0x0;
2073 retval = ERROR_OK;
2074 for (i = 0; i < image.num_sections; i++)
2075 {
2076 buffer = malloc(image.sections[i].size);
2077 if (buffer == NULL)
2078 {
2079 command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
2080 break;
2081 }
2082
2083 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
2084 {
2085 free(buffer);
2086 break;
2087 }
2088
2089 u32 offset=0;
2090 u32 length=buf_cnt;
2091
2092 /* DANGER!!! beware of unsigned comparision here!!! */
2093
2094 if ((image.sections[i].base_address+buf_cnt>=min_address)&&
2095 (image.sections[i].base_address<max_address))
2096 {
2097 if (image.sections[i].base_address<min_address)
2098 {
2099 /* clip addresses below */
2100 offset+=min_address-image.sections[i].base_address;
2101 length-=offset;
2102 }
2103
2104 if (image.sections[i].base_address+buf_cnt>max_address)
2105 {
2106 length-=(image.sections[i].base_address+buf_cnt)-max_address;
2107 }
2108
2109 if ((retval = target_write_buffer(target, image.sections[i].base_address+offset, length, buffer+offset)) != ERROR_OK)
2110 {
2111 free(buffer);
2112 break;
2113 }
2114 image_size += length;
2115 command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
2116 }
2117
2118 free(buffer);
2119 }
2120
2121 if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
2122 {
2123 image_close(&image);
2124 return retvaltemp;
2125 }
2126
2127 if (retval==ERROR_OK)
2128 {
2129 command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
2130 }
2131 free(duration_text);
2132
2133 image_close(&image);
2134
2135 return retval;
2136
2137 }
2138
2139 static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2140 {
2141 fileio_t fileio;
2142
2143 u32 address;
2144 u32 size;
2145 u8 buffer[560];
2146 int retval=ERROR_OK, retvaltemp;
2147
2148 duration_t duration;
2149 char *duration_text;
2150
2151 target_t *target = get_current_target(cmd_ctx);
2152
2153 if (argc != 3)
2154 {
2155 command_print(cmd_ctx, "usage: dump_image <filename> <address> <size>");
2156 return ERROR_OK;
2157 }
2158
2159 address = strtoul(args[1], NULL, 0);
2160 size = strtoul(args[2], NULL, 0);
2161
2162 if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
2163 {
2164 return ERROR_OK;
2165 }
2166
2167 duration_start_measure(&duration);
2168
2169 while (size > 0)
2170 {
2171 u32 size_written;
2172 u32 this_run_size = (size > 560) ? 560 : size;
2173
2174 retval = target_read_buffer(target, address, this_run_size, buffer);
2175 if (retval != ERROR_OK)
2176 {
2177 break;
2178 }
2179
2180 retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
2181 if (retval != ERROR_OK)
2182 {
2183 break;
2184 }
2185
2186 size -= this_run_size;
2187 address += this_run_size;
2188 }
2189
2190 if((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
2191 return retvaltemp;
2192
2193 if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
2194 return retvaltemp;
2195
2196 if (retval==ERROR_OK)
2197 {
2198 command_print(cmd_ctx, "dumped %lld byte in %s",
2199 fileio.size, duration_text);
2200 free(duration_text);
2201 }
2202
2203 return retval;
2204 }
2205
2206 static int handle_verify_image_command_internal(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, int verify)
2207 {
2208 u8 *buffer;
2209 u32 buf_cnt;
2210 u32 image_size;
2211 int i;
2212 int retval, retvaltemp;
2213 u32 checksum = 0;
2214 u32 mem_checksum = 0;
2215
2216 image_t image;
2217
2218 duration_t duration;
2219 char *duration_text;
2220
2221 target_t *target = get_current_target(cmd_ctx);
2222
2223 if (argc < 1)
2224 {
2225 return ERROR_COMMAND_SYNTAX_ERROR;
2226 }
2227
2228 if (!target)
2229 {
2230 LOG_ERROR("no target selected");
2231 return ERROR_FAIL;
2232 }
2233
2234 duration_start_measure(&duration);
2235
2236 if (argc >= 2)
2237 {
2238 image.base_address_set = 1;
2239 image.base_address = strtoul(args[1], NULL, 0);
2240 }
2241 else
2242 {
2243 image.base_address_set = 0;
2244 image.base_address = 0x0;
2245 }
2246
2247 image.start_address_set = 0;
2248
2249 if ((retval=image_open(&image, args[0], (argc == 3) ? args[2] : NULL)) != ERROR_OK)
2250 {
2251 return retval;
2252 }
2253
2254 image_size = 0x0;
2255 retval=ERROR_OK;
2256 for (i = 0; i < image.num_sections; i++)
2257 {
2258 buffer = malloc(image.sections[i].size);
2259 if (buffer == NULL)
2260 {
2261 command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
2262 break;
2263 }
2264 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
2265 {
2266 free(buffer);
2267 break;
2268 }
2269
2270 if (verify)
2271 {
2272 /* calculate checksum of image */
2273 image_calculate_checksum( buffer, buf_cnt, &checksum );
2274
2275 retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
2276 if( retval != ERROR_OK )
2277 {
2278 free(buffer);
2279 break;
2280 }
2281
2282 if( checksum != mem_checksum )
2283 {
2284 /* failed crc checksum, fall back to a binary compare */
2285 u8 *data;
2286
2287 command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
2288
2289 data = (u8*)malloc(buf_cnt);
2290
2291 /* Can we use 32bit word accesses? */
2292 int size = 1;
2293 int count = buf_cnt;
2294 if ((count % 4) == 0)
2295 {
2296 size *= 4;
2297 count /= 4;
2298 }
2299 retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
2300 if (retval == ERROR_OK)
2301 {
2302 u32 t;
2303 for (t = 0; t < buf_cnt; t++)
2304 {
2305 if (data[t] != buffer[t])
2306 {
2307 command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
2308 free(data);
2309 free(buffer);
2310 retval=ERROR_FAIL;
2311 goto done;
2312 }
2313 if ((t%16384)==0)
2314 {
2315 keep_alive();
2316 }
2317 }
2318 }
2319
2320 free(data);
2321 }
2322 } else
2323 {
2324 command_print(cmd_ctx, "address 0x%08x length 0x%08x", image.sections[i].base_address, buf_cnt);
2325 }
2326
2327 free(buffer);
2328 image_size += buf_cnt;
2329 }
2330 done:
2331
2332 if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
2333 {
2334 image_close(&image);
2335 return retvaltemp;
2336 }
2337
2338 if (retval==ERROR_OK)
2339 {
2340 command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
2341 }
2342 free(duration_text);
2343
2344 image_close(&image);
2345
2346 return retval;
2347 }
2348
2349 static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2350 {
2351 return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 1);
2352 }
2353
2354 static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2355 {
2356 return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 0);
2357 }
2358
2359 static int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2360 {
2361 int retval;
2362 target_t *target = get_current_target(cmd_ctx);
2363
2364 if (argc == 0)
2365 {
2366 breakpoint_t *breakpoint = target->breakpoints;
2367
2368 while (breakpoint)
2369 {
2370 if (breakpoint->type == BKPT_SOFT)
2371 {
2372 char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16);
2373 command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf);
2374 free(buf);
2375 }
2376 else
2377 {
2378 command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);
2379 }
2380 breakpoint = breakpoint->next;
2381 }
2382 }
2383 else if (argc >= 2)
2384 {
2385 int hw = BKPT_SOFT;
2386 u32 length = 0;
2387
2388 length = strtoul(args[1], NULL, 0);
2389
2390 if (argc >= 3)
2391 if (strcmp(args[2], "hw") == 0)
2392 hw = BKPT_HARD;
2393
2394 if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)
2395 {
2396 LOG_ERROR("Failure setting breakpoints");
2397 }
2398 else
2399 {
2400 command_print(cmd_ctx, "breakpoint added at address 0x%8.8lx",
2401 strtoul(args[0], NULL, 0));
2402 }
2403 }
2404 else
2405 {
2406 command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
2407 }
2408
2409 return ERROR_OK;
2410 }
2411
2412 static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2413 {
2414 target_t *target = get_current_target(cmd_ctx);
2415
2416 if (argc > 0)
2417 breakpoint_remove(target, strtoul(args[0], NULL, 0));
2418
2419 return ERROR_OK;
2420 }
2421
2422 static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2423 {
2424 target_t *target = get_current_target(cmd_ctx);
2425 int retval;
2426
2427 if (argc == 0)
2428 {
2429 watchpoint_t *watchpoint = target->watchpoints;
2430
2431 while (watchpoint)
2432 {
2433 command_print(cmd_ctx, "address: 0x%8.8x, len: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
2434 watchpoint = watchpoint->next;
2435 }
2436 }
2437 else if (argc >= 2)
2438 {
2439 enum watchpoint_rw type = WPT_ACCESS;
2440 u32 data_value = 0x0;
2441 u32 data_mask = 0xffffffff;
2442
2443 if (argc >= 3)
2444 {
2445 switch(args[2][0])
2446 {
2447 case 'r':
2448 type = WPT_READ;
2449 break;
2450 case 'w':
2451 type = WPT_WRITE;
2452 break;
2453 case 'a':
2454 type = WPT_ACCESS;
2455 break;
2456 default:
2457 command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
2458 return ERROR_OK;
2459 }
2460 }
2461 if (argc >= 4)
2462 {
2463 data_value = strtoul(args[3], NULL, 0);
2464 }
2465 if (argc >= 5)
2466 {
2467 data_mask = strtoul(args[4], NULL, 0);
2468 }
2469
2470 if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
2471 strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
2472 {
2473 LOG_ERROR("Failure setting breakpoints");
2474 }
2475 }
2476 else
2477 {
2478 command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
2479 }
2480
2481 return ERROR_OK;
2482 }
2483
2484 static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2485 {
2486 target_t *target = get_current_target(cmd_ctx);
2487
2488 if (argc > 0)
2489 watchpoint_remove(target, strtoul(args[0], NULL, 0));
2490
2491 return ERROR_OK;
2492 }
2493
2494 static int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
2495 {
2496 int retval;
2497 target_t *target = get_current_target(cmd_ctx);
2498 u32 va;
2499 u32 pa;
2500
2501 if (argc != 1)
2502 {
2503 return ERROR_COMMAND_SYNTAX_ERROR;
2504 }
2505 va = strtoul(args[0], NULL, 0);
2506
2507 retval = target->type->virt2phys(target, va, &pa);
2508 if (retval == ERROR_OK)
2509 {
2510 command_print(cmd_ctx, "Physical address 0x%08x", pa);
2511 }
2512 else
2513 {
2514 /* lower levels will have logged a detailed error which is
2515 * forwarded to telnet/GDB session.
2516 */
2517 }
2518 return retval;
2519 }
2520
2521 static void writeData(FILE *f, const void *data, size_t len)
2522 {
2523 size_t written = fwrite(data, len, 1, f);
2524 if (written != len)
2525 LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
2526 }
2527
2528 static void writeLong(FILE *f, int l)
2529 {
2530 int i;
2531 for (i=0; i<4; i++)
2532 {
2533 char c=(l>>(i*8))&0xff;
2534 writeData(f, &c, 1);
2535 }
2536
2537 }
2538
2539 static void writeString(FILE *f, char *s)
2540 {
2541 writeData(f, s, strlen(s));
2542 }
2543
2544 /* Dump a gmon.out histogram file. */
2545 static void writeGmon(u32 *samples, u32 sampleNum, char *filename)
2546 {
2547 u32 i;
2548 FILE *f=fopen(filename, "w");
2549 if (f==NULL)
2550 return;
2551 writeString(f, "gmon");
2552 writeLong(f, 0x00000001); /* Version */
2553 writeLong(f, 0); /* padding */
2554 writeLong(f, 0); /* padding */
2555 writeLong(f, 0); /* padding */
2556
2557 u8 zero = 0; /* GMON_TAG_TIME_HIST */
2558 writeData(f, &zero, 1);
2559
2560 /* figure out bucket size */
2561 u32 min=samples[0];
2562 u32 max=samples[0];
2563 for (i=0; i<sampleNum; i++)
2564 {
2565 if (min>samples[i])
2566 {
2567 min=samples[i];
2568 }
2569 if (max<samples[i])
2570 {
2571 max=samples[i];
2572 }
2573 }
2574
2575 int addressSpace=(max-min+1);
2576
2577 static const u32 maxBuckets = 256 * 1024; /* maximum buckets. */
2578 u32 length = addressSpace;
2579 if (length > maxBuckets)
2580 {
2581 length=maxBuckets;
2582 }
2583 int *buckets=malloc(sizeof(int)*length);
2584 if (buckets==NULL)
2585 {
2586 fclose(f);
2587 return;
2588 }
2589 memset(buckets, 0, sizeof(int)*length);
2590 for (i=0; i<sampleNum;i++)
2591 {
2592 u32 address=samples[i];
2593 long long a=address-min;
2594 long long b=length-1;
2595 long long c=addressSpace-1;
2596 int index=(a*b)/c; /* danger!!!! int32 overflows */
2597 buckets[index]++;
2598 }
2599
2600 /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
2601 writeLong(f, min); /* low_pc */
2602 writeLong(f, max); /* high_pc */
2603 writeLong(f, length); /* # of samples */
2604 writeLong(f, 64000000); /* 64MHz */
2605 writeString(f, "seconds");
2606 for (i=0; i<(15-strlen("seconds")); i++)
2607 writeData(f, &zero, 1);
2608 writeString(f, "s");
2609
2610 /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */
2611
2612 char *data=malloc(2*length);
2613 if (data!=NULL)
2614 {
2615 for (i=0; i<length;i++)
2616 {
2617 int val;
2618 val=buckets[i];
2619 if (val>65535)
2620 {
2621 val=65535;
2622 }
2623 data[i*2]=val&0xff;
2624 data[i*2+1]=(val>>8)&0xff;
2625 }
2626 free(buckets);
2627 writeData(f, data, length * 2);
2628 free(data);
2629 } else
2630 {
2631 free(buckets);
2632 }
2633
2634 fclose(f);
2635 }
2636
2637 /* profiling samples the CPU PC as quickly as OpenOCD is able, which will be used as a random sampling of PC */
2638 static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2639 {
2640 target_t *target = get_current_target(cmd_ctx);
2641 struct timeval timeout, now;
2642
2643 gettimeofday(&timeout, NULL);
2644 if (argc!=2)
2645 {
2646 return ERROR_COMMAND_SYNTAX_ERROR;
2647 }
2648 char *end;
2649 timeval_add_time(&timeout, strtoul(args[0], &end, 0), 0);
2650 if (*end)
2651 {
2652 return ERROR_OK;
2653 }
2654
2655 command_print(cmd_ctx, "Starting profiling. Halting and resuming the target as often as we can...");
2656
2657 static const int maxSample=10000;
2658 u32 *samples=malloc(sizeof(u32)*maxSample);
2659 if (samples==NULL)
2660 return ERROR_OK;
2661
2662 int numSamples=0;
2663 int retval=ERROR_OK;
2664 /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
2665 reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
2666
2667 for (;;)
2668 {
2669 target_poll(target);
2670 if (target->state == TARGET_HALTED)
2671 {
2672 u32 t=*((u32 *)reg->value);
2673 samples[numSamples++]=t;
2674 retval = target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
2675 target_poll(target);
2676 alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
2677 } else if (target->state == TARGET_RUNNING)
2678 {
2679 /* We want to quickly sample the PC. */
2680 if((retval = target_halt(target)) != ERROR_OK)
2681 {
2682 free(samples);
2683 return retval;
2684 }
2685 } else
2686 {
2687 command_print(cmd_ctx, "Target not halted or running");
2688 retval=ERROR_OK;
2689 break;
2690 }
2691 if (retval!=ERROR_OK)
2692 {
2693 break;
2694 }
2695
2696 gettimeofday(&now, NULL);
2697 if ((numSamples>=maxSample) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
2698 {
2699 command_print(cmd_ctx, "Profiling completed. %d samples.", numSamples);
2700 if((retval = target_poll(target)) != ERROR_OK)
2701 {
2702 free(samples);
2703 return retval;
2704 }
2705 if (target->state == TARGET_HALTED)
2706 {
2707 target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
2708 }
2709 if((retval = target_poll(target)) != ERROR_OK)
2710 {
2711 free(samples);
2712 return retval;
2713 }
2714 writeGmon(samples, numSamples, args[1]);
2715 command_print(cmd_ctx, "Wrote %s", args[1]);
2716 break;
2717 }
2718 }
2719 free(samples);
2720
2721 return ERROR_OK;
2722 }
2723
2724 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
2725 {
2726 char *namebuf;
2727 Jim_Obj *nameObjPtr, *valObjPtr;
2728 int result;
2729
2730 namebuf = alloc_printf("%s(%d)", varname, idx);
2731 if (!namebuf)
2732 return JIM_ERR;
2733
2734 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
2735 valObjPtr = Jim_NewIntObj(interp, val);
2736 if (!nameObjPtr || !valObjPtr)
2737 {
2738 free(namebuf);
2739 return JIM_ERR;
2740 }
2741
2742 Jim_IncrRefCount(nameObjPtr);
2743 Jim_IncrRefCount(valObjPtr);
2744 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
2745 Jim_DecrRefCount(interp, nameObjPtr);
2746 Jim_DecrRefCount(interp, valObjPtr);
2747 free(namebuf);
2748 /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
2749 return result;
2750 }
2751
2752 static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2753 {
2754 command_context_t *context;
2755 target_t *target;
2756
2757 context = Jim_GetAssocData(interp, "context");
2758 if (context == NULL)
2759 {
2760 LOG_ERROR("mem2array: no command context");
2761 return JIM_ERR;
2762 }
2763 target = get_current_target(context);
2764 if (target == NULL)
2765 {
2766 LOG_ERROR("mem2array: no current target");
2767 return JIM_ERR;
2768 }
2769
2770 return target_mem2array(interp, target, argc-1, argv+1);
2771 }
2772
2773 static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
2774 {
2775 long l;
2776 u32 width;
2777 int len;
2778 u32 addr;
2779 u32 count;
2780 u32 v;
2781 const char *varname;
2782 u8 buffer[4096];
2783 int n, e, retval;
2784 u32 i;
2785
2786 /* argv[1] = name of array to receive the data
2787 * argv[2] = desired width
2788 * argv[3] = memory address
2789 * argv[4] = count of times to read
2790 */
2791 if (argc != 4) {
2792 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
2793 return JIM_ERR;
2794 }
2795 varname = Jim_GetString(argv[0], &len);
2796 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
2797
2798 e = Jim_GetLong(interp, argv[1], &l);
2799 width = l;
2800 if (e != JIM_OK) {
2801 return e;
2802 }
2803
2804 e = Jim_GetLong(interp, argv[2], &l);
2805 addr = l;
2806 if (e != JIM_OK) {
2807 return e;
2808 }
2809 e = Jim_GetLong(interp, argv[3], &l);
2810 len = l;
2811 if (e != JIM_OK) {
2812 return e;
2813 }
2814 switch (width) {
2815 case 8:
2816 width = 1;
2817 break;
2818 case 16:
2819 width = 2;
2820 break;
2821 case 32:
2822 width = 4;
2823 break;
2824 default:
2825 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2826 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
2827 return JIM_ERR;
2828 }
2829 if (len == 0) {
2830 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2831 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
2832 return JIM_ERR;
2833 }
2834 if ((addr + (len * width)) < addr) {
2835 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2836 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
2837 return JIM_ERR;
2838 }
2839 /* absurd transfer size? */
2840 if (len > 65536) {
2841 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2842 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
2843 return JIM_ERR;
2844 }
2845
2846 if ((width == 1) ||
2847 ((width == 2) && ((addr & 1) == 0)) ||
2848 ((width == 4) && ((addr & 3) == 0))) {
2849 /* all is well */
2850 } else {
2851 char buf[100];
2852 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2853 sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
2854 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
2855 return JIM_ERR;
2856 }
2857
2858 /* Transfer loop */
2859
2860 /* index counter */
2861 n = 0;
2862 /* assume ok */
2863 e = JIM_OK;
2864 while (len) {
2865 /* Slurp... in buffer size chunks */
2866
2867 count = len; /* in objects.. */
2868 if (count > (sizeof(buffer)/width)) {
2869 count = (sizeof(buffer)/width);
2870 }
2871
2872 retval = target_read_memory( target, addr, width, count, buffer );
2873 if (retval != ERROR_OK) {
2874 /* BOO !*/
2875 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
2876 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2877 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
2878 e = JIM_ERR;
2879 len = 0;
2880 } else {
2881 v = 0; /* shut up gcc */
2882 for (i = 0 ;i < count ;i++, n++) {
2883 switch (width) {
2884 case 4:
2885 v = target_buffer_get_u32(target, &buffer[i*width]);
2886 break;
2887 case 2:
2888 v = target_buffer_get_u16(target, &buffer[i*width]);
2889 break;
2890 case 1:
2891 v = buffer[i] & 0x0ff;
2892 break;
2893 }
2894 new_int_array_element(interp, varname, n, v);
2895 }
2896 len -= count;
2897 }
2898 }
2899
2900 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
2901
2902 return JIM_OK;
2903 }
2904
2905 static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)
2906 {
2907 char *namebuf;
2908 Jim_Obj *nameObjPtr, *valObjPtr;
2909 int result;
2910 long l;
2911
2912 namebuf = alloc_printf("%s(%d)", varname, idx);
2913 if (!namebuf)
2914 return JIM_ERR;
2915
2916 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
2917 if (!nameObjPtr)
2918 {
2919 free(namebuf);
2920 return JIM_ERR;
2921 }
2922
2923 Jim_IncrRefCount(nameObjPtr);
2924 valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
2925 Jim_DecrRefCount(interp, nameObjPtr);
2926 free(namebuf);
2927 if (valObjPtr == NULL)
2928 return JIM_ERR;
2929
2930 result = Jim_GetLong(interp, valObjPtr, &l);
2931 /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
2932 *val = l;
2933 return result;
2934 }
2935
2936 static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2937 {
2938 command_context_t *context;
2939 target_t *target;
2940
2941 context = Jim_GetAssocData(interp, "context");
2942 if (context == NULL){
2943 LOG_ERROR("array2mem: no command context");
2944 return JIM_ERR;
2945 }
2946 target = get_current_target(context);
2947 if (target == NULL){
2948 LOG_ERROR("array2mem: no current target");
2949 return JIM_ERR;
2950 }
2951
2952 return target_array2mem( interp,target, argc-1, argv+1 );
2953 }
2954
2955 static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
2956 {
2957 long l;
2958 u32 width;
2959 int len;
2960 u32 addr;
2961 u32 count;
2962 u32 v;
2963 const char *varname;
2964 u8 buffer[4096];
2965 int n, e, retval;
2966 u32 i;
2967
2968 /* argv[1] = name of array to get the data
2969 * argv[2] = desired width
2970 * argv[3] = memory address
2971 * argv[4] = count to write
2972 */
2973 if (argc != 4) {
2974 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
2975 return JIM_ERR;
2976 }
2977 varname = Jim_GetString(argv[0], &len);
2978 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
2979
2980 e = Jim_GetLong(interp, argv[1], &l);
2981 width = l;
2982 if (e != JIM_OK) {
2983 return e;
2984 }
2985
2986 e = Jim_GetLong(interp, argv[2], &l);
2987 addr = l;
2988 if (e != JIM_OK) {
2989 return e;
2990 }
2991 e = Jim_GetLong(interp, argv[3], &l);
2992 len = l;
2993 if (e != JIM_OK) {
2994 return e;
2995 }
2996 switch (width) {
2997 case 8:
2998 width = 1;
2999 break;
3000 case 16:
3001 width = 2;
3002 break;
3003 case 32:
3004 width = 4;
3005 break;
3006 default:
3007 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3008 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
3009 return JIM_ERR;
3010 }
3011 if (len == 0) {
3012 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3013 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
3014 return JIM_ERR;
3015 }
3016 if ((addr + (len * width)) < addr) {
3017 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3018 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
3019 return JIM_ERR;
3020 }
3021 /* absurd transfer size? */
3022 if (len > 65536) {
3023 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3024 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
3025 return JIM_ERR;
3026 }
3027
3028 if ((width == 1) ||
3029 ((width == 2) && ((addr & 1) == 0)) ||
3030 ((width == 4) && ((addr & 3) == 0))) {
3031 /* all is well */
3032 } else {
3033 char buf[100];
3034 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3035 sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);
3036 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
3037 return JIM_ERR;
3038 }
3039
3040 /* Transfer loop */
3041
3042 /* index counter */
3043 n = 0;
3044 /* assume ok */
3045 e = JIM_OK;
3046 while (len) {
3047 /* Slurp... in buffer size chunks */
3048
3049 count = len; /* in objects.. */
3050 if (count > (sizeof(buffer)/width)) {
3051 count = (sizeof(buffer)/width);
3052 }
3053
3054 v = 0; /* shut up gcc */
3055 for (i = 0 ;i < count ;i++, n++) {
3056 get_int_array_element(interp, varname, n, &v);
3057 switch (width) {
3058 case 4:
3059 target_buffer_set_u32(target, &buffer[i*width], v);
3060 break;
3061 case 2:
3062 target_buffer_set_u16(target, &buffer[i*width], v);
3063 break;
3064 case 1:
3065 buffer[i] = v & 0x0ff;
3066 break;
3067 }
3068 }
3069 len -= count;
3070
3071 retval = target_write_memory(target, addr, width, count, buffer);
3072 if (retval != ERROR_OK) {
3073 /* BOO !*/
3074 LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
3075 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3076 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL);
3077 e = JIM_ERR;
3078 len = 0;
3079 }
3080 }
3081
3082 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
3083
3084 return JIM_OK;
3085 }
3086
3087 void target_all_handle_event( enum target_event e )
3088 {
3089 target_t *target;
3090
3091 LOG_DEBUG( "**all*targets: event: %d, %s",
3092 e,
3093 Jim_Nvp_value2name_simple( nvp_target_event, e )->name );
3094
3095 target = all_targets;
3096 while (target){
3097 target_handle_event( target, e );
3098 target = target->next;
3099 }
3100 }
3101
3102 void target_handle_event( target_t *target, enum target_event e )
3103 {
3104 target_event_action_t *teap;
3105 int done;
3106
3107 teap = target->event_action;
3108
3109 done = 0;
3110 while( teap ){
3111 if( teap->event == e ){
3112 done = 1;
3113 LOG_DEBUG( "target: (%d) %s (%s) event: %d (%s) action: %s\n",
3114 target->target_number,
3115 target->cmd_name,
3116 target->type->name,
3117 e,
3118 Jim_Nvp_value2name_simple( nvp_target_event, e )->name,
3119 Jim_GetString( teap->body, NULL ) );
3120 if (Jim_EvalObj( interp, teap->body )!=JIM_OK)
3121 {
3122 Jim_PrintErrorMessage(interp);
3123 }
3124 }
3125 teap = teap->next;
3126 }
3127 if( !done ){
3128 LOG_DEBUG( "event: %d %s - no action",
3129 e,
3130 Jim_Nvp_value2name_simple( nvp_target_event, e )->name );
3131 }
3132 }
3133
3134 enum target_cfg_param {
3135 TCFG_TYPE,
3136 TCFG_EVENT,
3137 TCFG_WORK_AREA_VIRT,
3138 TCFG_WORK_AREA_PHYS,
3139 TCFG_WORK_AREA_SIZE,
3140 TCFG_WORK_AREA_BACKUP,
3141 TCFG_ENDIAN,
3142 TCFG_VARIANT,
3143 TCFG_CHAIN_POSITION,
3144 };
3145
3146 static Jim_Nvp nvp_config_opts[] = {
3147 { .name = "-type", .value = TCFG_TYPE },
3148 { .name = "-event", .value = TCFG_EVENT },
3149 { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT },
3150 { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS },
3151 { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE },
3152 { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
3153 { .name = "-endian" , .value = TCFG_ENDIAN },
3154 { .name = "-variant", .value = TCFG_VARIANT },
3155 { .name = "-chain-position", .value = TCFG_CHAIN_POSITION },
3156
3157 { .name = NULL, .value = -1 }
3158 };
3159
3160 static int target_configure( Jim_GetOptInfo *goi, target_t *target )
3161 {
3162 Jim_Nvp *n;
3163 Jim_Obj *o;
3164 jim_wide w;
3165 char *cp;
3166 int e;
3167
3168 /* parse config or cget options ... */
3169 while( goi->argc > 0 ){
3170 Jim_SetEmptyResult( goi->interp );
3171 /* Jim_GetOpt_Debug( goi ); */
3172
3173 if( target->type->target_jim_configure ){
3174 /* target defines a configure function */
3175 /* target gets first dibs on parameters */
3176 e = (*(target->type->target_jim_configure))( target, goi );
3177 if( e == JIM_OK ){
3178 /* more? */
3179 continue;
3180 }
3181 if( e == JIM_ERR ){
3182 /* An error */
3183 return e;
3184 }
3185 /* otherwise we 'continue' below */
3186 }
3187 e = Jim_GetOpt_Nvp( goi, nvp_config_opts, &n );
3188 if( e != JIM_OK ){
3189 Jim_GetOpt_NvpUnknown( goi, nvp_config_opts, 0 );
3190 return e;
3191 }
3192 switch( n->value ){
3193 case TCFG_TYPE:
3194 /* not setable */
3195 if( goi->isconfigure ){
3196 Jim_SetResult_sprintf( goi->interp, "not setable: %s", n->name );
3197 return JIM_ERR;
3198 } else {
3199 no_params:
3200 if( goi->argc != 0 ){
3201 Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "NO PARAMS");
3202 return JIM_ERR;
3203 }
3204 }
3205 Jim_SetResultString( goi->interp, target->type->name, -1 );
3206 /* loop for more */
3207 break;
3208 case TCFG_EVENT:
3209 if( goi->argc == 0 ){
3210 Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
3211 return JIM_ERR;
3212 }
3213
3214 e = Jim_GetOpt_Nvp( goi, nvp_target_event, &n );
3215 if( e != JIM_OK ){
3216 Jim_GetOpt_NvpUnknown( goi, nvp_target_event, 1 );
3217 return e;
3218 }
3219
3220 if( goi->isconfigure ){
3221 if( goi->argc != 1 ){
3222 Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
3223 return JIM_ERR;
3224 }
3225 } else {
3226 if( goi->argc != 0 ){
3227 Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
3228 return JIM_ERR;
3229 }
3230 }
3231
3232 {
3233 target_event_action_t *teap;
3234
3235 teap = target->event_action;
3236 /* replace existing? */
3237 while( teap ){
3238 if( teap->event == (enum target_event)n->value ){
3239 break;
3240 }
3241 teap = teap->next;
3242 }
3243
3244 if( goi->isconfigure ){
3245 if( teap == NULL ){
3246 /* create new */
3247 teap = calloc( 1, sizeof(*teap) );
3248 }
3249 teap->event = n->value;
3250 Jim_GetOpt_Obj( goi, &o );
3251 if( teap->body ){
3252 Jim_DecrRefCount( interp, teap->body );
3253 }
3254 teap->body = Jim_DuplicateObj( goi->interp, o );
3255 /*
3256 * FIXME:
3257 * Tcl/TK - "tk events" have a nice feature.
3258 * See the "BIND" command.
3259 * We should support that here.
3260 * You can specify %X and %Y in the event code.
3261 * The idea is: %T - target name.
3262 * The idea is: %N - target number
3263 * The idea is: %E - event name.
3264 */
3265 Jim_IncrRefCount( teap->body );
3266
3267 /* add to head of event list */
3268 teap->next = target->event_action;
3269 target->event_action = teap;
3270 Jim_SetEmptyResult(goi->interp);
3271 } else {
3272 /* get */
3273 if( teap == NULL ){
3274 Jim_SetEmptyResult( goi->interp );
3275 } else {
3276 Jim_SetResult( goi->interp, Jim_DuplicateObj( goi->interp, teap->body ) );
3277 }
3278 }
3279 }
3280 /* loop for more */
3281 break;
3282
3283 case TCFG_WORK_AREA_VIRT:
3284 if( goi->isconfigure ){
3285 target_free_all_working_areas(target);
3286 e = Jim_GetOpt_Wide( goi, &w );
3287 if( e != JIM_OK ){
3288 return e;
3289 }
3290 target->working_area_virt = w;
3291 } else {
3292 if( goi->argc != 0 ){
3293 goto no_params;
3294 }
3295 }
3296 Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_virt ) );
3297 /* loop for more */
3298 break;
3299
3300 case TCFG_WORK_AREA_PHYS:
3301 if( goi->isconfigure ){
3302 target_free_all_working_areas(target);
3303 e = Jim_GetOpt_Wide( goi, &w );
3304 if( e != JIM_OK ){
3305 return e;
3306 }
3307 target->working_area_phys = w;
3308 } else {
3309 if( goi->argc != 0 ){
3310 goto no_params;
3311 }
3312 }
3313 Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_phys ) );
3314 /* loop for more */
3315 break;
3316
3317 case TCFG_WORK_AREA_SIZE:
3318 if( goi->isconfigure ){
3319 target_free_all_working_areas(target);
3320 e = Jim_GetOpt_Wide( goi, &w );
3321 if( e != JIM_OK ){
3322 return e;
3323 }
3324 target->working_area_size = w;
3325 } else {
3326 if( goi->argc != 0 ){
3327 goto no_params;
3328 }
3329 }
3330 Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_size ) );
3331 /* loop for more */
3332 break;
3333
3334 case TCFG_WORK_AREA_BACKUP:
3335 if( goi->isconfigure ){
3336 target_free_all_working_areas(target);
3337 e = Jim_GetOpt_Wide( goi, &w );
3338 if( e != JIM_OK ){
3339 return e;
3340 }
3341 /* make this exactly 1 or 0 */
3342 target->backup_working_area = (!!w);
3343 } else {
3344 if( goi->argc != 0 ){
3345 goto no_params;
3346 }
3347 }
3348 Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_size ) );
3349 /* loop for more e*/
3350 break;
3351
3352 case TCFG_ENDIAN:
3353 if( goi->isconfigure ){
3354 e = Jim_GetOpt_Nvp( goi, nvp_target_endian, &n );
3355 if( e != JIM_OK ){
3356 Jim_GetOpt_NvpUnknown( goi, nvp_target_endian, 1 );
3357 return e;
3358 }
3359 target->endianness = n->value;
3360 } else {
3361 if( goi->argc != 0 ){
3362 goto no_params;
3363 }
3364 }
3365 n = Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness );
3366 if( n->name == NULL ){
3367 target->endianness = TARGET_LITTLE_ENDIAN;
3368 n = Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness );
3369 }
3370 Jim_SetResultString( goi->interp, n->name, -1 );
3371 /* loop for more */
3372 break;
3373
3374 case TCFG_VARIANT:
3375 if( goi->isconfigure ){
3376 if( goi->argc < 1 ){
3377 Jim_SetResult_sprintf( goi->interp,
3378 "%s ?STRING?",
3379 n->name );
3380 return JIM_ERR;
3381 }
3382 if( target->variant ){
3383 free((void *)(target->variant));
3384 }
3385 e = Jim_GetOpt_String( goi, &cp, NULL );
3386 target->variant = strdup(cp);
3387 } else {
3388 if( goi->argc != 0 ){
3389 goto no_params;
3390 }
3391 }
3392 Jim_SetResultString( goi->interp, target->variant,-1 );
3393 /* loop for more */
3394 break;
3395 case TCFG_CHAIN_POSITION:
3396 if( goi->isconfigure ){
3397 Jim_Obj *o;
3398 jtag_tap_t *tap;
3399 target_free_all_working_areas(target);
3400 e = Jim_GetOpt_Obj( goi, &o );
3401 if( e != JIM_OK ){
3402 return e;
3403 }
3404 tap = jtag_TapByJimObj( goi->interp, o );
3405 if( tap == NULL ){
3406 return JIM_ERR;
3407 }
3408 /* make this exactly 1 or 0 */
3409 target->tap = tap;
3410 } else {
3411 if( goi->argc != 0 ){
3412 goto no_params;
3413 }
3414 }
3415 Jim_SetResultString( interp, target->tap->dotted_name, -1 );
3416 /* loop for more e*/
3417 break;
3418 }
3419 } /* while( goi->argc ) */
3420
3421
3422 /* done - we return */
3423 return JIM_OK;
3424 }
3425
3426 /** this is the 'tcl' handler for the target specific command */
3427 static int tcl_target_func( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
3428 {
3429 Jim_GetOptInfo goi;
3430 jim_wide a,b,c;
3431 int x,y,z;
3432 u8 target_buf[32];
3433 Jim_Nvp *n;
3434 target_t *target;
3435 struct command_context_s *cmd_ctx;
3436 int e;
3437
3438 enum {
3439 TS_CMD_CONFIGURE,
3440 TS_CMD_CGET,
3441
3442 TS_CMD_MWW, TS_CMD_MWH, TS_CMD_MWB,
3443 TS_CMD_MDW, TS_CMD_MDH, TS_CMD_MDB,
3444 TS_CMD_MRW, TS_CMD_MRH, TS_CMD_MRB,
3445 TS_CMD_MEM2ARRAY, TS_CMD_ARRAY2MEM,
3446 TS_CMD_EXAMINE,
3447 TS_CMD_POLL,
3448 TS_CMD_RESET,
3449 TS_CMD_HALT,
3450 TS_CMD_WAITSTATE,
3451 TS_CMD_EVENTLIST,
3452 TS_CMD_CURSTATE,
3453 TS_CMD_INVOKE_EVENT,
3454 };
3455
3456 static const Jim_Nvp target_options[] = {
3457 { .name = "configure", .value = TS_CMD_CONFIGURE },
3458 { .name = "cget", .value = TS_CMD_CGET },
3459 { .name = "mww", .value = TS_CMD_MWW },
3460 { .name = "mwh", .value = TS_CMD_MWH },
3461 { .name = "mwb", .value = TS_CMD_MWB },
3462 { .name = "mdw", .value = TS_CMD_MDW },
3463 { .name = "mdh", .value = TS_CMD_MDH },
3464 { .name = "mdb", .value = TS_CMD_MDB },
3465 { .name = "mem2array", .value = TS_CMD_MEM2ARRAY },
3466 { .name = "array2mem", .value = TS_CMD_ARRAY2MEM },
3467 { .name = "eventlist", .value = TS_CMD_EVENTLIST },
3468 { .name = "curstate", .value = TS_CMD_CURSTATE },
3469
3470 { .name = "arp_examine", .value = TS_CMD_EXAMINE },
3471 { .name = "arp_poll", .value = TS_CMD_POLL },
3472 { .name = "arp_reset", .value = TS_CMD_RESET },
3473 { .name = "arp_halt", .value = TS_CMD_HALT },
3474 { .name = "arp_waitstate", .value = TS_CMD_WAITSTATE },
3475 { .name = "invoke-event", .value = TS_CMD_INVOKE_EVENT },
3476
3477 { .name = NULL, .value = -1 },
3478 };
3479
3480 /* go past the "command" */
3481 Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 );
3482
3483 target = Jim_CmdPrivData( goi.interp );
3484 cmd_ctx = Jim_GetAssocData(goi.interp, "context");
3485
3486 /* commands here are in an NVP table */
3487 e = Jim_GetOpt_Nvp( &goi, target_options, &n );
3488 if( e != JIM_OK ){
3489 Jim_GetOpt_NvpUnknown( &goi, target_options, 0 );
3490 return e;
3491 }
3492 /* Assume blank result */
3493 Jim_SetEmptyResult( goi.interp );
3494
3495 switch( n->value ){
3496 case TS_CMD_CONFIGURE:
3497 if( goi.argc < 2 ){
3498 Jim_WrongNumArgs( goi.interp, goi.argc, goi.argv, "missing: -option VALUE ...");
3499 return JIM_ERR;
3500 }
3501 goi.isconfigure = 1;
3502 return target_configure( &goi, target );
3503 case TS_CMD_CGET:
3504 // some things take params
3505 if( goi.argc < 1 ){
3506 Jim_WrongNumArgs( goi.interp, 0, goi.argv, "missing: ?-option?");
3507 return JIM_ERR;
3508 }
3509 goi.isconfigure = 0;
3510 return target_configure( &goi, target );
3511 break;
3512 case TS_CMD_MWW:
3513 case TS_CMD_MWH:
3514 case TS_CMD_MWB:
3515 /* argv[0] = cmd
3516 * argv[1] = address
3517 * argv[2] = data
3518 * argv[3] = optional count.
3519 */
3520
3521 if( (goi.argc == 3) || (goi.argc == 4) ){
3522 /* all is well */
3523 } else {
3524 mwx_error:
3525 Jim_SetResult_sprintf( goi.interp, "expected: %s ADDR DATA [COUNT]", n->name );
3526 return JIM_ERR;
3527 }
3528
3529 e = Jim_GetOpt_Wide( &goi, &a );
3530 if( e != JIM_OK ){
3531 goto mwx_error;
3532 }
3533
3534 e = Jim_GetOpt_Wide( &goi, &b );
3535 if( e != JIM_OK ){
3536 goto mwx_error;
3537 }
3538 if( goi.argc ){
3539 e = Jim_GetOpt_Wide( &goi, &c );
3540 if( e != JIM_OK ){
3541 goto mwx_error;
3542 }
3543 } else {
3544 c = 1;
3545 }
3546
3547 switch( n->value ){
3548 case TS_CMD_MWW:
3549 target_buffer_set_u32( target, target_buf, b );
3550 b = 4;
3551 break;
3552 case TS_CMD_MWH:
3553 target_buffer_set_u16( target, target_buf, b );
3554 b = 2;
3555 break;
3556 case TS_CMD_MWB:
3557 target_buffer_set_u8( target, target_buf, b );
3558 b = 1;
3559 break;
3560 }
3561 for( x = 0 ; x < c ; x++ ){
3562 e = target_write_memory( target, a, b, 1, target_buf );
3563 if( e != ERROR_OK ){
3564 Jim_SetResult_sprintf( interp, "Error writing @ 0x%08x: %d\n", (int)(a), e );
3565 return JIM_ERR;
3566 }
3567 /* b = width */
3568 a = a + b;
3569 }
3570 return JIM_OK;
3571 break;
3572
3573 /* display */
3574 case TS_CMD_MDW:
3575 case TS_CMD_MDH:
3576 case TS_CMD_MDB:
3577 /* argv[0] = command
3578 * argv[1] = address
3579 * argv[2] = optional count
3580 */
3581 if( (goi.argc == 2) || (goi.argc == 3) ){
3582 Jim_SetResult_sprintf( goi.interp, "expected: %s ADDR [COUNT]", n->name );
3583 return JIM_ERR;
3584 }
3585 e = Jim_GetOpt_Wide( &goi, &a );
3586 if( e != JIM_OK ){
3587 return JIM_ERR;
3588 }
3589 if( goi.argc ){
3590 e = Jim_GetOpt_Wide( &goi, &c );
3591 if( e != JIM_OK ){
3592 return JIM_ERR;
3593 }
3594 } else {
3595 c = 1;
3596 }
3597 b = 1; /* shut up gcc */
3598 switch( n->value ){
3599 case TS_CMD_MDW:
3600 b = 4;
3601 break;
3602 case TS_CMD_MDH:
3603 b = 2;
3604 break;
3605 case TS_CMD_MDB:
3606 b = 1;
3607 break;
3608 }
3609
3610 /* convert to "bytes" */
3611 c = c * b;
3612 /* count is now in 'BYTES' */
3613 while( c > 0 ){
3614 y = c;
3615 if( y > 16 ){
3616 y = 16;
3617 }
3618 e = target_read_memory( target, a, b, y / b, target_buf );
3619 if( e != ERROR_OK ){
3620 Jim_SetResult_sprintf( interp, "error reading target @ 0x%08lx", (int)(a) );
3621 return JIM_ERR;
3622 }
3623
3624 Jim_fprintf( interp, interp->cookie_stdout, "0x%08x ", (int)(a) );
3625 switch( b ){
3626 case 4:
3627 for( x = 0 ; (x < 16) && (x < y) ; x += 4 ){
3628 z = target_buffer_get_u32( target, &(target_buf[ x * 4 ]) );
3629 Jim_fprintf( interp, interp->cookie_stdout, "%08x ", (int)(z) );
3630 }
3631 for( ; (x < 16) ; x += 4 ){
3632 Jim_fprintf( interp, interp->cookie_stdout, " " );
3633 }
3634 break;
3635 case 2:
3636 for( x = 0 ; (x < 16) && (x < y) ; x += 2 ){
3637 z = target_buffer_get_u16( target, &(target_buf[ x * 2 ]) );
3638 Jim_fprintf( interp, interp->cookie_stdout, "%04x ", (int)(z) );
3639 }
3640 for( ; (x < 16) ; x += 2 ){
3641 Jim_fprintf( interp, interp->cookie_stdout, " " );
3642 }
3643 break;
3644 case 1:
3645 default:
3646 for( x = 0 ; (x < 16) && (x < y) ; x += 1 ){
3647 z = target_buffer_get_u8( target, &(target_buf[ x * 4 ]) );
3648 Jim_fprintf( interp, interp->cookie_stdout, "%02x ", (int)(z) );
3649 }
3650 for( ; (x < 16) ; x += 1 ){
3651 Jim_fprintf( interp, interp->cookie_stdout, " " );
3652 }
3653 break;
3654 }
3655 /* ascii-ify the bytes */
3656 for( x = 0 ; x < y ; x++ ){
3657 if( (target_buf[x] >= 0x20) &&
3658 (target_buf[x] <= 0x7e) ){
3659 /* good */
3660 } else {
3661 /* smack it */
3662 target_buf[x] = '.';
3663 }
3664 }
3665 /* space pad */
3666 while( x < 16 ){
3667 target_buf[x] = ' ';
3668 x++;
3669 }
3670 /* terminate */
3671 target_buf[16] = 0;
3672 /* print - with a newline */
3673 Jim_fprintf( interp, interp->cookie_stdout, "%s\n", target_buf );
3674 /* NEXT... */
3675 c -= 16;
3676 a += 16;
3677 }
3678 return JIM_OK;
3679 case TS_CMD_MEM2ARRAY:
3680 return target_mem2array( goi.interp, target, goi.argc, goi.argv );
3681 break;
3682 case TS_CMD_ARRAY2MEM:
3683 return target_array2mem( goi.interp, target, goi.argc, goi.argv );
3684 break;
3685 case TS_CMD_EXAMINE:
3686 if( goi.argc ){
3687 Jim_WrongNumArgs( goi.interp, 2, argv, "[no parameters]");
3688 return JIM_ERR;
3689 }
3690 e = target->type->examine( target );
3691 if( e != ERROR_OK ){
3692 Jim_SetResult_sprintf( interp, "examine-fails: %d", e );
3693 return JIM_ERR;
3694 }
3695 return JIM_OK;
3696 case TS_CMD_POLL:
3697 if( goi.argc ){
3698 Jim_WrongNumArgs( goi.interp, 2, argv, "[no parameters]");
3699 return JIM_ERR;
3700 }
3701 if( !(target_was_examined(target)) ){
3702 e = ERROR_TARGET_NOT_EXAMINED;
3703 } else {
3704 e = target->type->poll( target );
3705 }
3706 if( e != ERROR_OK ){
3707 Jim_SetResult_sprintf( interp, "poll-fails: %d", e );
3708 return JIM_ERR;
3709 } else {
3710 return JIM_OK;
3711 }
3712 break;
3713 case TS_CMD_RESET:
3714 if( goi.argc != 2 ){
3715 Jim_WrongNumArgs( interp, 2, argv, "t|f|assert|deassert BOOL");
3716 return JIM_ERR;
3717 }
3718 e = Jim_GetOpt_Nvp( &goi, nvp_assert, &n );
3719 if( e != JIM_OK ){
3720 Jim_GetOpt_NvpUnknown( &goi, nvp_assert, 1 );
3721 return e;
3722 }
3723 /* the halt or not param */
3724 e = Jim_GetOpt_Wide( &goi, &a);
3725 if( e != JIM_OK ){
3726 return e;
3727 }
3728 /* determine if we should halt or not. */
3729 target->reset_halt = !!a;
3730 /* When this happens - all workareas are invalid. */
3731 target_free_all_working_areas_restore(target, 0);
3732
3733 /* do the assert */
3734 if( n->value == NVP_ASSERT ){
3735 target->type->assert_reset( target );
3736 } else {
3737 target->type->deassert_reset( target );
3738 }
3739 return JIM_OK;
3740 case TS_CMD_HALT:
3741 if( goi.argc ){
3742 Jim_WrongNumArgs( goi.interp, 0, argv, "halt [no parameters]");
3743 return JIM_ERR;
3744 }
3745 target->type->halt( target );
3746 return JIM_OK;
3747 case TS_CMD_WAITSTATE:
3748 /* params: <name> statename timeoutmsecs */
3749 if( goi.argc != 2 ){
3750 Jim_SetResult_sprintf( goi.interp, "%s STATENAME TIMEOUTMSECS", n->name );
3751 return JIM_ERR;
3752 }
3753 e = Jim_GetOpt_Nvp( &goi, nvp_target_state, &n );
3754 if( e != JIM_OK ){
3755 Jim_GetOpt_NvpUnknown( &goi, nvp_target_state,1 );
3756 return e;
3757 }
3758 e = Jim_GetOpt_Wide( &goi, &a );
3759 if( e != JIM_OK ){
3760 return e;
3761 }
3762 e = target_wait_state( target, n->value, a );
3763 if( e != ERROR_OK ){
3764 Jim_SetResult_sprintf( goi.interp,
3765 "target: %s wait %s fails (%d) %s",
3766 target->cmd_name,
3767 n->name,
3768 e, target_strerror_safe(e) );
3769 return JIM_ERR;
3770 } else {
3771 return JIM_OK;
3772 }
3773 case TS_CMD_EVENTLIST:
3774 /* List for human, Events defined for this target.
3775 * scripts/programs should use 'name cget -event NAME'
3776 */
3777 {
3778 target_event_action_t *teap;
3779 teap = target->event_action;
3780 command_print( cmd_ctx, "Event actions for target (%d) %s\n",
3781 target->target_number,
3782 target->cmd_name );
3783 command_print( cmd_ctx, "%-25s | Body", "Event");
3784 command_print( cmd_ctx, "------------------------- | ----------------------------------------");
3785 while( teap ){
3786 command_print( cmd_ctx,
3787 "%-25s | %s",
3788 Jim_Nvp_value2name_simple( nvp_target_event, teap->event )->name,
3789 Jim_GetString( teap->body, NULL ) );
3790 teap = teap->next;
3791 }
3792 command_print( cmd_ctx, "***END***");
3793 return JIM_OK;
3794 }
3795 case TS_CMD_CURSTATE:
3796 if( goi.argc != 0 ){
3797 Jim_WrongNumArgs( goi.interp, 0, argv, "[no parameters]");
3798 return JIM_ERR;
3799 }
3800 Jim_SetResultString( goi.interp,
3801 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name,-1);
3802 return JIM_OK;
3803 case TS_CMD_INVOKE_EVENT:
3804 if( goi.argc != 1 ){
3805 Jim_SetResult_sprintf( goi.interp, "%s ?EVENTNAME?",n->name);
3806 return JIM_ERR;
3807 }
3808 e = Jim_GetOpt_Nvp( &goi, nvp_target_event, &n );
3809 if( e != JIM_OK ){
3810 Jim_GetOpt_NvpUnknown( &goi, nvp_target_event, 1 );
3811 return e;
3812 }
3813 target_handle_event( target, n->value );
3814 return JIM_OK;
3815 }
3816 return JIM_ERR;
3817 }
3818
3819 static int target_create( Jim_GetOptInfo *goi )
3820 {
3821 Jim_Obj *new_cmd;
3822 Jim_Cmd *cmd;
3823 const char *cp;
3824 char *cp2;
3825 int e;
3826 int x;
3827 target_t *target;
3828 struct command_context_s *cmd_ctx;
3829
3830 cmd_ctx = Jim_GetAssocData(goi->interp, "context");
3831 if( goi->argc < 3 ){
3832 Jim_WrongNumArgs( goi->interp, 1, goi->argv, "?name? ?type? ..options...");
3833 return JIM_ERR;
3834 }
3835
3836 /* COMMAND */
3837 Jim_GetOpt_Obj( goi, &new_cmd );
3838 /* does this command exist? */
3839 cmd = Jim_GetCommand( goi->interp, new_cmd, JIM_ERRMSG );
3840 if( cmd ){
3841 cp = Jim_GetString( new_cmd, NULL );
3842 Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
3843 return JIM_ERR;
3844 }
3845
3846 /* TYPE */
3847 e = Jim_GetOpt_String( goi, &cp2, NULL );
3848 cp = cp2;
3849 /* now does target type exist */
3850 for( x = 0 ; target_types[x] ; x++ ){
3851 if( 0 == strcmp( cp, target_types[x]->name ) ){
3852 /* found */
3853 break;
3854 }
3855 }
3856 if( target_types[x] == NULL ){
3857 Jim_SetResult_sprintf( goi->interp, "Unknown target type %s, try one of ", cp );
3858 for( x = 0 ; target_types[x] ; x++ ){
3859 if( target_types[x+1] ){
3860 Jim_AppendStrings( goi->interp,
3861 Jim_GetResult(goi->interp),
3862 target_types[x]->name,
3863 ", ", NULL);
3864 } else {
3865 Jim_AppendStrings( goi->interp,
3866 Jim_GetResult(goi->interp),
3867 " or ",
3868 target_types[x]->name,NULL );
3869 }
3870 }
3871 return JIM_ERR;
3872 }
3873
3874 /* Create it */
3875 target = calloc(1,sizeof(target_t));
3876 /* set target number */
3877 target->target_number = new_target_number();
3878
3879 /* allocate memory for each unique target type */
3880 target->type = (target_type_t*)calloc(1,sizeof(target_type_t));
3881
3882 memcpy( target->type, target_types[x], sizeof(target_type_t));
3883
3884 /* will be set by "-endian" */
3885 target->endianness = TARGET_ENDIAN_UNKNOWN;
3886
3887 target->working_area = 0x0;
3888 target->working_area_size = 0x0;
3889 target->working_areas = NULL;
3890 target->backup_working_area = 0;
3891
3892 target->state = TARGET_UNKNOWN;
3893 target->debug_reason = DBG_REASON_UNDEFINED;
3894 target->reg_cache = NULL;
3895 target->breakpoints = NULL;
3896 target->watchpoints = NULL;
3897 target->next = NULL;
3898 target->arch_info = NULL;
3899
3900 target->display = 1;
3901
3902 /* initialize trace information */
3903 target->trace_info = malloc(sizeof(trace_t));
3904 target->trace_info->num_trace_points = 0;
3905 target->trace_info->trace_points_size = 0;
3906 target->trace_info->trace_points = NULL;
3907 target->trace_info->trace_history_size = 0;
3908 target->trace_info->trace_history = NULL;
3909 target->trace_info->trace_history_pos = 0;
3910 target->trace_info->trace_history_overflowed = 0;
3911
3912 target->dbgmsg = NULL;
3913 target->dbg_msg_enabled = 0;
3914
3915 target->endianness = TARGET_ENDIAN_UNKNOWN;
3916
3917 /* Do the rest as "configure" options */
3918 goi->isconfigure = 1;
3919 e = target_configure( goi, target);
3920
3921 if (target->tap == NULL)
3922 {
3923 Jim_SetResultString( interp, "-chain-position required when creating target", -1);
3924 e=JIM_ERR;
3925 }
3926
3927 if( e != JIM_OK ){
3928 free( target->type );
3929 free( target );
3930 return e;
3931 }
3932
3933 if( target->endianness == TARGET_ENDIAN_UNKNOWN ){
3934 /* default endian to little if not specified */
3935 target->endianness = TARGET_LITTLE_ENDIAN;
3936 }
3937
3938 /* incase variant is not set */
3939 if (!target->variant)
3940 target->variant = strdup("");
3941
3942 /* create the target specific commands */
3943 if( target->type->register_commands ){
3944 (*(target->type->register_commands))( cmd_ctx );
3945 }
3946 if( target->type->target_create ){
3947 (*(target->type->target_create))( target, goi->interp );
3948 }
3949
3950 /* append to end of list */
3951 {
3952 target_t **tpp;
3953 tpp = &(all_targets);
3954 while( *tpp ){
3955 tpp = &( (*tpp)->next );
3956 }
3957 *tpp = target;
3958 }
3959
3960 cp = Jim_GetString( new_cmd, NULL );
3961 target->cmd_name = strdup(cp);
3962
3963 /* now - create the new target name command */
3964 e = Jim_CreateCommand( goi->interp,
3965 /* name */
3966 cp,
3967 tcl_target_func, /* C function */
3968 target, /* private data */
3969 NULL ); /* no del proc */
3970
3971 return e;
3972 }
3973
3974 static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
3975 {
3976 int x,r,e;
3977 jim_wide w;
3978 struct command_context_s *cmd_ctx;
3979 target_t *target;
3980 Jim_GetOptInfo goi;
3981 enum tcmd {
3982 /* TG = target generic */
3983 TG_CMD_CREATE,
3984 TG_CMD_TYPES,
3985 TG_CMD_NAMES,
3986 TG_CMD_CURRENT,
3987 TG_CMD_NUMBER,
3988 TG_CMD_COUNT,
3989 };
3990 const char *target_cmds[] = {
3991 "create", "types", "names", "current", "number",
3992 "count",
3993 NULL /* terminate */
3994 };
3995
3996 LOG_DEBUG("Target command params:");
3997 LOG_DEBUG("%s", Jim_Debug_ArgvString(interp, argc, argv));
3998
3999 cmd_ctx = Jim_GetAssocData( interp, "context" );
4000
4001 Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 );
4002
4003 if( goi.argc == 0 ){
4004 Jim_WrongNumArgs(interp, 1, argv, "missing: command ...");
4005 return JIM_ERR;
4006 }
4007
4008 /* Jim_GetOpt_Debug( &goi ); */
4009 r = Jim_GetOpt_Enum( &goi, target_cmds, &x );
4010 if( r != JIM_OK ){
4011 return r;
4012 }
4013
4014 switch(x){
4015 default:
4016 Jim_Panic(goi.interp,"Why am I here?");
4017 return JIM_ERR;
4018 case TG_CMD_CURRENT:
4019 if( goi.argc != 0 ){
4020 Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters");
4021 return JIM_ERR;
4022 }
4023 Jim_SetResultString( goi.interp, get_current_target( cmd_ctx )->cmd_name, -1 );
4024 return JIM_OK;
4025 case TG_CMD_TYPES:
4026 if( goi.argc != 0 ){
4027 Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters" );
4028 return JIM_ERR;
4029 }
4030 Jim_SetResult( goi.interp, Jim_NewListObj( goi.interp, NULL, 0 ) );
4031 for( x = 0 ; target_types[x] ; x++ ){
4032 Jim_ListAppendElement( goi.interp,
4033 Jim_GetResult(goi.interp),
4034 Jim_NewStringObj( goi.interp, target_types[x]->name, -1 ) );
4035 }
4036 return JIM_OK;
4037 case TG_CMD_NAMES:
4038 if( goi.argc != 0 ){
4039 Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters" );
4040 return JIM_ERR;
4041 }
4042 Jim_SetResult( goi.interp, Jim_NewListObj( goi.interp, NULL, 0 ) );
4043 target = all_targets;
4044 while( target ){
4045 Jim_ListAppendElement( goi.interp,
4046 Jim_GetResult(goi.interp),
4047 Jim_NewStringObj( goi.interp, target->cmd_name, -1 ) );
4048 target = target->next;
4049 }
4050 return JIM_OK;
4051 case TG_CMD_CREATE:
4052 if( goi.argc < 3 ){
4053 Jim_WrongNumArgs( goi.interp, goi.argc, goi.argv, "?name ... config options ...");
4054 return JIM_ERR;
4055 }
4056 return target_create( &goi );
4057 break;
4058 case TG_CMD_NUMBER:
4059 if( goi.argc != 1 ){
4060 Jim_SetResult_sprintf( goi.interp, "expected: target number ?NUMBER?");
4061 return JIM_ERR;
4062 }
4063 e = Jim_GetOpt_Wide( &goi, &w );
4064 if( e != JIM_OK ){
4065 return JIM_ERR;
4066 }
4067 {
4068 target_t *t;
4069 t = get_target_by_num(w);
4070 if( t == NULL ){
4071 Jim_SetResult_sprintf( goi.interp,"Target: number %d does not exist", (int)(w));
4072 return JIM_ERR;
4073 }
4074 Jim_SetResultString( goi.interp, t->cmd_name, -1 );
4075 return JIM_OK;
4076 }
4077 case TG_CMD_COUNT:
4078 if( goi.argc != 0 ){
4079 Jim_WrongNumArgs( goi.interp, 0, goi.argv, "<no parameters>");
4080 return JIM_ERR;
4081 }
4082 Jim_SetResult( goi.interp,
4083 Jim_NewIntObj( goi.interp, max_target_number()));
4084 return JIM_OK;
4085 }
4086
4087 return JIM_ERR;
4088 }
4089
4090
4091 struct FastLoad
4092 {
4093 u32 address;
4094 u8 *data;
4095 int length;
4096
4097 };
4098
4099 static int fastload_num;
4100 static struct FastLoad *fastload;
4101
4102 static void free_fastload(void)
4103 {
4104 if (fastload!=NULL)
4105 {
4106 int i;
4107 for (i=0; i<fastload_num; i++)
4108 {
4109 if (fastload[i].data)
4110 free(fastload[i].data);
4111 }
4112 free(fastload);
4113 fastload=NULL;
4114 }
4115 }
4116
4117
4118
4119
4120 static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4121 {
4122 u8 *buffer;
4123 u32 buf_cnt;
4124 u32 image_size;
4125 u32 min_address=0;
4126 u32 max_address=0xffffffff;
4127 int i;
4128 int retval;
4129
4130 image_t image;
4131
4132 duration_t duration;
4133 char *duration_text;
4134
4135 if ((argc < 1)||(argc > 5))
4136 {
4137 return ERROR_COMMAND_SYNTAX_ERROR;
4138 }
4139
4140 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
4141 if (argc >= 2)
4142 {
4143 image.base_address_set = 1;
4144 image.base_address = strtoul(args[1], NULL, 0);
4145 }
4146 else
4147 {
4148 image.base_address_set = 0;
4149 }
4150
4151
4152 image.start_address_set = 0;
4153
4154 if (argc>=4)
4155 {
4156 min_address=strtoul(args[3], NULL, 0);
4157 }
4158 if (argc>=5)
4159 {
4160 max_address=strtoul(args[4], NULL, 0)+min_address;
4161 }
4162
4163 if (min_address>max_address)
4164 {
4165 return ERROR_COMMAND_SYNTAX_ERROR;
4166 }
4167
4168 duration_start_measure(&duration);
4169
4170 if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
4171 {
4172 return ERROR_OK;
4173 }
4174
4175 image_size = 0x0;
4176 retval = ERROR_OK;
4177 fastload_num=image.num_sections;
4178 fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
4179 if (fastload==NULL)
4180 {
4181 image_close(&image);
4182 return ERROR_FAIL;
4183 }
4184 memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
4185 for (i = 0; i < image.num_sections; i++)
4186 {
4187 buffer = malloc(image.sections[i].size);
4188 if (buffer == NULL)
4189 {
4190 command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
4191 break;
4192 }
4193
4194 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
4195 {
4196 free(buffer);
4197 break;
4198 }
4199
4200 u32 offset=0;
4201 u32 length=buf_cnt;
4202
4203
4204 /* DANGER!!! beware of unsigned comparision here!!! */
4205
4206 if ((image.sections[i].base_address+buf_cnt>=min_address)&&
4207 (image.sections[i].base_address<max_address))
4208 {
4209 if (image.sections[i].base_address<min_address)
4210 {
4211 /* clip addresses below */
4212 offset+=min_address-image.sections[i].base_address;
4213 length-=offset;
4214 }
4215
4216 if (image.sections[i].base_address+buf_cnt>max_address)
4217 {
4218 length-=(image.sections[i].base_address+buf_cnt)-max_address;
4219 }
4220
4221 fastload[i].address=image.sections[i].base_address+offset;
4222 fastload[i].data=malloc(length);
4223 if (fastload[i].data==NULL)
4224 {
4225 free(buffer);
4226 break;
4227 }
4228 memcpy(fastload[i].data, buffer+offset, length);
4229 fastload[i].length=length;
4230
4231 image_size += length;
4232 command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
4233 }
4234
4235 free(buffer);
4236 }
4237
4238 duration_stop_measure(&duration, &duration_text);
4239 if (retval==ERROR_OK)
4240 {
4241 command_print(cmd_ctx, "Loaded %u bytes in %s", image_size, duration_text);
4242 command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
4243 }
4244 free(duration_text);
4245
4246 image_close(&image);
4247
4248 if (retval!=ERROR_OK)
4249 {
4250 free_fastload();
4251 }
4252
4253 return retval;
4254 }
4255
4256 static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4257 {
4258 if (argc>0)
4259 return ERROR_COMMAND_SYNTAX_ERROR;
4260 if (fastload==NULL)
4261 {
4262 LOG_ERROR("No image in memory");
4263 return ERROR_FAIL;
4264 }
4265 int i;
4266 int ms=timeval_ms();
4267 int size=0;
4268 int retval=ERROR_OK;
4269 for (i=0; i<fastload_num;i++)
4270 {
4271 target_t *target = get_current_target(cmd_ctx);
4272 command_print(cmd_ctx, "Write to 0x%08x, length 0x%08x", fastload[i].address, fastload[i].length);
4273 if (retval==ERROR_OK)
4274 {
4275 retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
4276 }
4277 size+=fastload[i].length;
4278 }
4279 int after=timeval_ms();
4280 command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
4281 return retval;
4282 }

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)