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

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)