target.c 111 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 yvind Harboe                                 *
6
7
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
 *   Copyright (C) 2008, Duane Ellis                                       *
 *   openocd@duaneeellis.com                                               *
 *                                                                         *
11
12
13
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
14
15
16
 *   Copyright (C) 2008 by Rick Altherr                                    *
 *   kc8apf@kc8apf.net>                                                    *
 *                                                                         *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "target.h"
37
#include "target_type.h"
38
#include "target_request.h"
39
40
41
42
#include "time_support.h"
#include "register.h"
#include "trace.h"
#include "image.h"
43
44
45
#include "jtag.h"


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);

static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
70

71
72
static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
73
static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv);
74

75
76
77
static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv);
static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv);

78
/* targets */
79
80
81
82
83
84
85
86
87
extern target_type_t arm7tdmi_target;
extern target_type_t arm720t_target;
extern target_type_t arm9tdmi_target;
extern target_type_t arm920t_target;
extern target_type_t arm966e_target;
extern target_type_t arm926ejs_target;
extern target_type_t feroceon_target;
extern target_type_t xscale_target;
extern target_type_t cortexm3_target;
88
extern target_type_t cortexa8_target;
oharboe's avatar
oharboe committed
89
extern target_type_t arm11_target;
ntfreak's avatar
ntfreak committed
90
extern target_type_t mips_m4k_target;
91
extern target_type_t avr_target;
92
93
94
95
96
97
98
99
100
101
102
103

target_type_t *target_types[] =
{
	&arm7tdmi_target,
	&arm9tdmi_target,
	&arm920t_target,
	&arm720t_target,
	&arm966e_target,
	&arm926ejs_target,
	&feroceon_target,
	&xscale_target,
	&cortexm3_target,
104
	&cortexa8_target,
oharboe's avatar
oharboe committed
105
	&arm11_target,
ntfreak's avatar
ntfreak committed
106
	&mips_m4k_target,
107
	&avr_target,
108
109
110
	NULL,
};

111
target_t *all_targets = NULL;
112
113
114
target_event_callback_t *target_event_callbacks = NULL;
target_timer_callback_t *target_timer_callbacks = NULL;

115
116
117
118
119
120
121
122
const Jim_Nvp nvp_assert[] = {
	{ .name = "assert", NVP_ASSERT },
	{ .name = "deassert", NVP_DEASSERT },
	{ .name = "T", NVP_ASSERT },
	{ .name = "F", NVP_DEASSERT },
	{ .name = "t", NVP_ASSERT },
	{ .name = "f", NVP_DEASSERT },
	{ .name = NULL, .value = -1 }
123
124
};

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const Jim_Nvp nvp_error_target[] = {
	{ .value = ERROR_TARGET_INVALID, .name = "err-invalid" },
	{ .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" },
	{ .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
	{ .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" },
	{ .value = ERROR_TARGET_FAILURE, .name = "err-failure" },
	{ .value = ERROR_TARGET_UNALIGNED_ACCESS   , .name = "err-unaligned-access" },
	{ .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" },
	{ .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" },
	{ .value = ERROR_TARGET_TRANSLATION_FAULT  , .name = "err-translation-fault" },
	{ .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" },
	{ .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" },
	{ .value = -1, .name = NULL }
};

const char *target_strerror_safe( int err )
{
	const Jim_Nvp *n;

	n = Jim_Nvp_value2name_simple( nvp_error_target, err );
	if( n->name == NULL ){
		return "unknown";
	} else {
		return n->name;
	}
}

152
static const Jim_Nvp nvp_target_event[] = {
153
154
	{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
	{ .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
155

156
	{ .value = TARGET_EVENT_EARLY_HALTED, .name = "early-halted" },
157
158
159
160
161
	{ .value = TARGET_EVENT_HALTED, .name = "halted" },
	{ .value = TARGET_EVENT_RESUMED, .name = "resumed" },
	{ .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
	{ .value = TARGET_EVENT_RESUME_END, .name = "resume-end" },

162
163
164
	{ .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
	{ .name = "gdb-end", .value = TARGET_EVENT_GDB_END },

165
	/* historical name */
166

167
	{ .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
168
169
170
171
172
173
174
175
176

	{ .value = TARGET_EVENT_RESET_ASSERT_PRE,    .name = "reset-assert-pre" },
	{ .value = TARGET_EVENT_RESET_ASSERT_POST,   .name = "reset-assert-post" },
	{ .value = TARGET_EVENT_RESET_DEASSERT_PRE,  .name = "reset-deassert-pre" },
	{ .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
	{ .value = TARGET_EVENT_RESET_HALT_PRE,      .name = "reset-halt-pre" },
	{ .value = TARGET_EVENT_RESET_HALT_POST,     .name = "reset-halt-post" },
	{ .value = TARGET_EVENT_RESET_WAIT_PRE,      .name = "reset-wait-pre" },
	{ .value = TARGET_EVENT_RESET_WAIT_POST,     .name = "reset-wait-post" },
177
178
179
	{ .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" },
	{ .value = TARGET_EVENT_RESET_END, .name = "reset-end" },

180
	{ .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
181
	{ .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	{ .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
	{ .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" },

	{ .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" },
	{ .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" },

	{ .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" },
	{ .value = TARGET_EVENT_GDB_FLASH_WRITE_END  , .name = "gdb-flash-write-end"   },

	{ .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
	{ .value = TARGET_EVENT_GDB_FLASH_ERASE_END  , .name = "gdb-flash-erase-end" },

	{ .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
	{ .value = TARGET_EVENT_RESUMED     , .name = "resume-ok" },
	{ .value = TARGET_EVENT_RESUME_END  , .name = "resume-end" },

	{ .name = NULL, .value = -1 }
200
201
};

202
203
204
205
206
207
208
const Jim_Nvp nvp_target_state[] = {
	{ .name = "unknown", .value = TARGET_UNKNOWN },
	{ .name = "running", .value = TARGET_RUNNING },
	{ .name = "halted",  .value = TARGET_HALTED },
	{ .name = "reset",   .value = TARGET_RESET },
	{ .name = "debug-running", .value = TARGET_DEBUG_RUNNING },
	{ .name = NULL, .value = -1 },
209
210
};

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
const Jim_Nvp nvp_target_debug_reason [] = {
	{ .name = "debug-request"            , .value = DBG_REASON_DBGRQ },
	{ .name = "breakpoint"               , .value = DBG_REASON_BREAKPOINT },
	{ .name = "watchpoint"               , .value = DBG_REASON_WATCHPOINT },
	{ .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
	{ .name = "single-step"              , .value = DBG_REASON_SINGLESTEP },
	{ .name = "target-not-halted"        , .value = DBG_REASON_NOTHALTED  },
	{ .name = "undefined"                , .value = DBG_REASON_UNDEFINED },
	{ .name = NULL, .value = -1 },
};

const Jim_Nvp nvp_target_endian[] = {
	{ .name = "big",    .value = TARGET_BIG_ENDIAN },
	{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
	{ .name = "be",     .value = TARGET_BIG_ENDIAN },
226
	{ .name = "le",     .value = TARGET_LITTLE_ENDIAN },
227
228
229
	{ .name = NULL,     .value = -1 },
};

230
231
232
233
234
235
236
237
const Jim_Nvp nvp_reset_modes[] = {
	{ .name = "unknown", .value = RESET_UNKNOWN },
	{ .name = "run"    , .value = RESET_RUN },
	{ .name = "halt"   , .value = RESET_HALT },
	{ .name = "init"   , .value = RESET_INIT },
	{ .name = NULL     , .value = -1 },
};

238
static int max_target_number(void)
239
240
241
242
243
244
245
246
247
248
249
250
251
252
{
	target_t *t;
	int x;

	x = -1;
	t = all_targets;
	while( t ){
		if( x < t->target_number ){
			x = (t->target_number)+1;
		}
		t = t->next;
	}
	return x;
}
253
254

/* determine the number of the new target */
255
static int new_target_number(void)
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
{
	target_t *t;
	int x;

	/* number is 0 based */
	x = -1;
	t = all_targets;
	while(t){
		if( x < t->target_number ){
			x = t->target_number;
		}
		t = t->next;
	}
	return x+1;
}

zwelch's avatar
zwelch committed
272
static int target_continuous_poll = 1;
273
274

/* read a u32 from a buffer in target memory endianness */
275
u32 target_buffer_get_u32(target_t *target, const u8 *buffer)
276
277
278
279
280
281
282
283
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u32(buffer);
	else
		return be_to_h_u32(buffer);
}

/* read a u16 from a buffer in target memory endianness */
284
u16 target_buffer_get_u16(target_t *target, const u8 *buffer)
285
286
287
288
289
290
291
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u16(buffer);
	else
		return be_to_h_u16(buffer);
}

292
/* read a u8 from a buffer in target memory endianness */
293
u8 target_buffer_get_u8(target_t *target, const u8 *buffer)
294
295
296
297
{
	return *buffer & 0x0ff;
}

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/* write a u32 to a buffer in target memory endianness */
void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u32_to_le(buffer, value);
	else
		h_u32_to_be(buffer, value);
}

/* write a u16 to a buffer in target memory endianness */
void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u16_to_le(buffer, value);
	else
		h_u16_to_be(buffer, value);
}

316
317
318
319
320
321
/* write a u8 to a buffer in target memory endianness */
void target_buffer_set_u8(target_t *target, u8 *buffer, u8 value)
{
	*buffer = value;
}

322
323
324
325
326
327
328
329
330
331
332
333
334
335
/* return a pointer to a configured target; id is name or number */
target_t *get_target(const char *id)
{
	target_t *target;

	/* try as tcltarget name */
	for (target = all_targets; target; target = target->next) {
		if (target->cmd_name == NULL)
			continue;
		if (strcmp(id, target->cmd_name) == 0)
			return target;
	}

	/* no match, try as number */
336
337
	unsigned num;
	if (parse_uint(id, &num) != ERROR_OK)
338
339
340
		return NULL;

	for (target = all_targets; target; target = target->next) {
341
		if (target->target_number == (int)num)
342
343
344
345
346
347
			return target;
	}

	return NULL;
}

348
/* returns a pointer to the n-th configured target */
349
static target_t *get_target_by_num(int num)
350
{
351
	target_t *target = all_targets;
352

353
354
	while (target){
		if( target->target_number == num ){
355
			return target;
356
		}
357
358
359
360
361
362
363
364
		target = target->next;
	}

	return NULL;
}

int get_num_by_target(target_t *query_target)
{
365
	return query_target->target_number;
366
367
368
369
370
}

target_t* get_current_target(command_context_t *cmd_ctx)
{
	target_t *target = get_target_by_num(cmd_ctx->current_target);
oharboe's avatar
oharboe committed
371

372
373
	if (target == NULL)
	{
374
		LOG_ERROR("BUG: current_target out of bounds");
375
376
377
		exit(-1);
	}

oharboe's avatar
oharboe committed
378
	return target;
379
380
}

381
382
383
int target_poll(struct target_s *target)
{
	/* We can't poll until after examine */
384
	if (!target_was_examined(target))
385
386
387
388
389
390
391
392
393
394
	{
		/* Fail silently lest we pollute the log */
		return ERROR_FAIL;
	}
	return target->type->poll(target);
}

int target_halt(struct target_s *target)
{
	/* We can't poll until after examine */
395
	if (!target_was_examined(target))
396
397
398
399
400
401
402
403
404
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->halt(target);
}

int target_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
{
405
	int retval;
oharboe's avatar
oharboe committed
406

407
	/* We can't poll until after examine */
408
	if (!target_was_examined(target))
409
410
411
412
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
413

oharboe's avatar
oharboe committed
414
415
416
417
	/* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can
	 * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?)
	 * the application.
	 */
418
419
	if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
420

421
	return retval;
422
423
}

oharboe's avatar
oharboe committed
424
int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
425
426
{
	char buf[100];
427
	int retval;
428
429
430
431
432
433
434
	Jim_Nvp *n;
	n = Jim_Nvp_value2name_simple( nvp_reset_modes, reset_mode );
	if( n->name == NULL ){
		LOG_ERROR("invalid reset mode");
		return ERROR_FAIL;
	}

435
436
437
438
	/* disable polling during reset to make reset event scripts
	 * more predictable, i.e. dr/irscan & pathmove in events will
	 * not have JTAG operations injected into the middle of a sequence.
	 */
zwelch's avatar
zwelch committed
439
440
	int save_poll = target_continuous_poll;
	target_continuous_poll = 0;
441

442
	sprintf( buf, "ocd_process_reset %s", n->name );
443
444
	retval = Jim_Eval( interp, buf );

zwelch's avatar
zwelch committed
445
	target_continuous_poll = save_poll;
446

447
448
	if(retval != JIM_OK) {
		Jim_PrintErrorMessage(interp);
449
450
		return ERROR_FAIL;
	}
451
452

	/* We want any events to be processed before the prompt */
453
	retval = target_call_timer_callbacks_now();
454

455
	return retval;
456
457
}

458
459
460
461
462
463
464
465
466
467
468
469
static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
{
	*physical = virtual;
	return ERROR_OK;
}

static int default_mmu(struct target_s *target, int *enabled)
{
	*enabled = 0;
	return ERROR_OK;
}

470
static int default_examine(struct target_s *target)
471
{
472
	target_set_examined(target);
473
474
475
	return ERROR_OK;
}

zwelch's avatar
zwelch committed
476
477
478
479
480
int target_examine_one(struct target_s *target)
{
	return target->type->examine(target);
}

481
482
/* Targets that correctly implement init+examine, i.e.
 * no communication with target during init:
oharboe's avatar
oharboe committed
483
484
 *
 * XScale
485
 */
ntfreak's avatar
ntfreak committed
486
int target_examine(void)
487
488
{
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
489
490
491
	target_t *target;

	for (target = all_targets; target; target = target->next)
492
	{
zwelch's avatar
zwelch committed
493
494
		if (!target->tap->enabled)
			continue;
zwelch's avatar
zwelch committed
495
		if ((retval = target_examine_one(target)) != ERROR_OK)
496
497
498
499
			return retval;
	}
	return retval;
}
zwelch's avatar
zwelch committed
500
501
502
503
const char *target_get_name(struct target_s *target)
{
	return target->type->name;
}
504

505
506
static int target_write_memory_imp(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
{
507
	if (!target_was_examined(target))
508
509
510
511
512
513
514
515
516
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->write_memory_imp(target, address, size, count, buffer);
}

static int target_read_memory_imp(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
{
517
	if (!target_was_examined(target))
518
519
520
521
522
523
524
525
526
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->read_memory_imp(target, address, size, count, buffer);
}

static int target_soft_reset_halt_imp(struct target_s *target)
{
527
	if (!target_was_examined(target))
528
529
530
531
532
533
534
535
536
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->soft_reset_halt_imp(target);
}

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)
{
537
	if (!target_was_examined(target))
538
539
540
541
542
543
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	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);
}
544

zwelch's avatar
zwelch committed
545
546
547
548
549
550
int target_read_memory(struct target_s *target,
		u32 address, u32 size, u32 count, u8 *buffer)
{
	return target->type->read_memory(target, address, size, count, buffer);
}

zwelch's avatar
zwelch committed
551
552
553
554
555
int target_write_memory(struct target_s *target,
		u32 address, u32 size, u32 count, u8 *buffer)
{
	return target->type->write_memory(target, address, size, count, buffer);
}
zwelch's avatar
zwelch committed
556
557
558
559
560
561
int target_bulk_write_memory(struct target_s *target,
		u32 address, u32 count, u8 *buffer)
{
	return target->type->bulk_write_memory(target, address, count, buffer);
}

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
int target_add_breakpoint(struct target_s *target,
		struct breakpoint_s *breakpoint)
{
	return target->type->add_breakpoint(target, breakpoint);
}
int target_remove_breakpoint(struct target_s *target,
		struct breakpoint_s *breakpoint)
{
	return target->type->remove_breakpoint(target, breakpoint);
}

int target_add_watchpoint(struct target_s *target,
		struct watchpoint_s *watchpoint)
{
	return target->type->add_watchpoint(target, watchpoint);
}
int target_remove_watchpoint(struct target_s *target,
		struct watchpoint_s *watchpoint)
{
	return target->type->remove_watchpoint(target, watchpoint);
}
zwelch's avatar
zwelch committed
583

zwelch's avatar
zwelch committed
584
585
586
587
588
int target_get_gdb_reg_list(struct target_s *target,
		struct reg_s **reg_list[], int *reg_list_size)
{
	return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
}
zwelch's avatar
zwelch committed
589
590
591
592
593
594
int target_step(struct target_s *target,
		int current, u32 address, int handle_breakpoints)
{
	return target->type->step(target, current, address, handle_breakpoints);
}

zwelch's avatar
zwelch committed
595

zwelch's avatar
zwelch committed
596
597
598
599
600
601
602
603
604
605
606
int target_run_algorithm(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)
{
	return target->type->run_algorithm(target,
			num_mem_params, mem_params, num_reg_params, reg_param,
			entry_point, exit_point, timeout_ms, arch_info);
}

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
/// @returns @c true if the target has been examined.
bool target_was_examined(struct target_s *target)
{
	return target->type->examined;
}
/// Sets the @c examined flag for the given target.
void target_set_examined(struct target_s *target)
{
	target->type->examined = true;
}
// Reset the @c examined flag for the given target.
void target_reset_examined(struct target_s *target)
{
	target->type->examined = false;
}

zwelch's avatar
zwelch committed
623

624
625
int target_init(struct command_context_s *cmd_ctx)
{
626
	target_t *target = all_targets;
627
	int retval;
oharboe's avatar
oharboe committed
628

629
630
	while (target)
	{
631
		target_reset_examined(target);
632
633
634
635
		if (target->type->examine == NULL)
		{
			target->type->examine = default_examine;
		}
oharboe's avatar
oharboe committed
636

637
		if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
638
		{
zwelch's avatar
zwelch committed
639
			LOG_ERROR("target '%s' init failed", target_get_name(target));
640
			return retval;
641
		}
oharboe's avatar
oharboe committed
642

643
644
645
646
647
		/* Set up default functions if none are provided by target */
		if (target->type->virt2phys == NULL)
		{
			target->type->virt2phys = default_virt2phys;
		}
648
649
650
651
652
653
654
655
656
657
658
659
660
		target->type->virt2phys = default_virt2phys;
		/* a non-invasive way(in terms of patches) to add some code that
		 * runs before the type->write/read_memory implementation
		 */
		target->type->write_memory_imp = target->type->write_memory;
		target->type->write_memory = target_write_memory_imp;
		target->type->read_memory_imp = target->type->read_memory;
		target->type->read_memory = target_read_memory_imp;
		target->type->soft_reset_halt_imp = target->type->soft_reset_halt;
		target->type->soft_reset_halt = target_soft_reset_halt_imp;
		target->type->run_algorithm_imp = target->type->run_algorithm;
		target->type->run_algorithm = target_run_algorithm_imp;

661
662
663
664
665
666
		if (target->type->mmu == NULL)
		{
			target->type->mmu = default_mmu;
		}
		target = target->next;
	}
oharboe's avatar
oharboe committed
667

668
	if (all_targets)
669
	{
670
671
672
673
		if((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK)
			return retval;
		if((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK)
			return retval;
674
	}
oharboe's avatar
oharboe committed
675

676
677
678
679
680
681
	return ERROR_OK;
}

int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
{
	target_event_callback_t **callbacks_p = &target_event_callbacks;
oharboe's avatar
oharboe committed
682

683
684
685
686
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
687

688
689
690
691
692
693
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
694

695
696
697
698
	(*callbacks_p) = malloc(sizeof(target_event_callback_t));
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
699

700
701
702
703
704
705
706
	return ERROR_OK;
}

int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
{
	target_timer_callback_t **callbacks_p = &target_timer_callbacks;
	struct timeval now;
oharboe's avatar
oharboe committed
707

708
709
710
711
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
712

713
714
715
716
717
718
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
719

720
721
722
723
	(*callbacks_p) = malloc(sizeof(target_timer_callback_t));
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->periodic = periodic;
	(*callbacks_p)->time_ms = time_ms;
oharboe's avatar
oharboe committed
724

725
726
727
728
729
730
731
732
733
	gettimeofday(&now, NULL);
	(*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
	time_ms -= (time_ms % 1000);
	(*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
	if ((*callbacks_p)->when.tv_usec > 1000000)
	{
		(*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
		(*callbacks_p)->when.tv_sec += 1;
	}
oharboe's avatar
oharboe committed
734

735
736
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
737

738
739
740
741
742
743
744
	return ERROR_OK;
}

int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
{
	target_event_callback_t **p = &target_event_callbacks;
	target_event_callback_t *c = target_event_callbacks;
oharboe's avatar
oharboe committed
745

746
747
748
749
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
750

751
752
753
754
755
756
757
758
759
760
761
762
763
	while (c)
	{
		target_event_callback_t *next = c->next;
		if ((c->callback == callback) && (c->priv == priv))
		{
			*p = next;
			free(c);
			return ERROR_OK;
		}
		else
			p = &(c->next);
		c = next;
	}
oharboe's avatar
oharboe committed
764

765
766
767
768
769
770
771
	return ERROR_OK;
}

int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
{
	target_timer_callback_t **p = &target_timer_callbacks;
	target_timer_callback_t *c = target_timer_callbacks;
oharboe's avatar
oharboe committed
772

773
774
775
776
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
777

778
779
780
781
782
783
784
785
786
787
788
789
790
	while (c)
	{
		target_timer_callback_t *next = c->next;
		if ((c->callback == callback) && (c->priv == priv))
		{
			*p = next;
			free(c);
			return ERROR_OK;
		}
		else
			p = &(c->next);
		c = next;
	}
oharboe's avatar
oharboe committed
791

792
793
794
795
796
797
798
	return ERROR_OK;
}

int target_call_event_callbacks(target_t *target, enum target_event event)
{
	target_event_callback_t *callback = target_event_callbacks;
	target_event_callback_t *next_callback;
oharboe's avatar
oharboe committed
799

800
801
802
803
804
805
	if (event == TARGET_EVENT_HALTED)
	{
		/* execute early halted first */
		target_call_event_callbacks(target, TARGET_EVENT_EARLY_HALTED);
	}

806
807
	LOG_DEBUG("target event %i (%s)",
			  event,
808
			  Jim_Nvp_value2name_simple( nvp_target_event, event )->name );
oharboe's avatar
oharboe committed
809

810
	target_handle_event( target, event );
811

812
813
814
815
816
817
	while (callback)
	{
		next_callback = callback->next;
		callback->callback(target, event, callback->priv);
		callback = next_callback;
	}
oharboe's avatar
oharboe committed
818

819
820
821
	return ERROR_OK;
}

822
823
static int target_timer_callback_periodic_restart(
		target_timer_callback_t *cb, struct timeval *now)
824
{
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
	int time_ms = cb->time_ms;
	cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000;
	time_ms -= (time_ms % 1000);
	cb->when.tv_sec = now->tv_sec + time_ms / 1000;
	if (cb->when.tv_usec > 1000000)
	{
		cb->when.tv_usec = cb->when.tv_usec - 1000000;
		cb->when.tv_sec += 1;
	}
	return ERROR_OK;
}

static int target_call_timer_callback(target_timer_callback_t *cb,
		struct timeval *now)
{
	cb->callback(cb->priv);
841

842
843
844
845
846
847
848
849
	if (cb->periodic)
		return target_timer_callback_periodic_restart(cb, now);

	return target_unregister_timer_callback(cb->callback, cb->priv);
}

static int target_call_timer_callbacks_check_time(int checktime)
{
oharboe's avatar
   
oharboe committed
850
851
	keep_alive();

852
	struct timeval now;
853
	gettimeofday(&now, NULL);
oharboe's avatar
oharboe committed
854

855
	target_timer_callback_t *callback = target_timer_callbacks;
856
857
	while (callback)
	{
858
859
860
861
862
863
864
865
		// cleaning up may unregister and free this callback
		target_timer_callback_t *next_callback = callback->next;

		bool call_it = callback->callback &&
			((!checktime && callback->periodic) ||
			  now.tv_sec > callback->when.tv_sec ||
			 (now.tv_sec == callback->when.tv_sec &&
			  now.tv_usec >= callback->when.tv_usec));
oharboe's avatar
oharboe committed
866

867
		if (call_it)
868
		{
869
870
871
			int retval = target_call_timer_callback(callback, &now);
			if (retval != ERROR_OK)
				return retval;
872
		}
oharboe's avatar
oharboe committed
873

874
875
		callback = next_callback;
	}
oharboe's avatar
oharboe committed
876

877
878
879
	return ERROR_OK;
}

oharboe's avatar
oharboe committed
880
int target_call_timer_callbacks(void)
881
882
883
884
885
{
	return target_call_timer_callbacks_check_time(1);
}

/* invoke periodic callbacks immediately */
oharboe's avatar
oharboe committed
886
int target_call_timer_callbacks_now(void)
887
{
oharboe's avatar
   
oharboe committed
888
	return target_call_timer_callbacks_check_time(0);
889
890
}

891
892
893
894
int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)
{
	working_area_t *c = target->working_areas;
	working_area_t *new_wa = NULL;
oharboe's avatar
oharboe committed
895

896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
	/* Reevaluate working area address based on MMU state*/
	if (target->working_areas == NULL)
	{
		int retval;
		int enabled;
		retval = target->type->mmu(target, &enabled);
		if (retval != ERROR_OK)
		{
			return retval;
		}
		if (enabled)
		{
			target->working_area = target->working_area_virt;
		}
		else
		{
			target->working_area = target->working_area_phys;
		}
	}
oharboe's avatar
oharboe committed
915

916
917
918
	/* only allocate multiples of 4 byte */
	if (size % 4)
	{
919
		LOG_ERROR("BUG: code tried to allocate unaligned number of bytes, padding");
920
921
		size = CEIL(size, 4);
	}
oharboe's avatar
oharboe committed
922

923
924
925
926
927
928
929
930
931
932
	/* see if there's already a matching working area */
	while (c)
	{
		if ((c->free) && (c->size == size))
		{
			new_wa = c;
			break;
		}
		c = c->next;
	}
oharboe's avatar
oharboe committed
933

934
935
936
937
938
939
	/* if not, allocate a new one */
	if (!new_wa)
	{
		working_area_t **p = &target->working_areas;
		u32 first_free = target->working_area;
		u32 free_size = target->working_area_size;
oharboe's avatar
oharboe committed
940

941
		LOG_DEBUG("allocating new working area");
oharboe's avatar
oharboe committed
942

943
944
945
946
947
948
949
950
		c = target->working_areas;
		while (c)
		{
			first_free += c->size;
			free_size -= c->size;
			p = &c->next;
			c = c->next;
		}
oharboe's avatar
oharboe committed
951

952
953
		if (free_size < size)
		{
954
			LOG_WARNING("not enough working area available(requested %d, free %d)", size, free_size);
955
956
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
oharboe's avatar
oharboe committed
957

958
959
960
961
		new_wa = malloc(sizeof(working_area_t));
		new_wa->next = NULL;
		new_wa->size = size;
		new_wa->address = first_free;
oharboe's avatar
oharboe committed
962

963
964
		if (target->backup_working_area)
		{
965
			int retval;
966
			new_wa->backup = malloc(new_wa->size);
zwelch's avatar
zwelch committed
967
			if((retval = target_read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup)) != ERROR_OK)
968
969
970
971
972
			{
				free(new_wa->backup);
				free(new_wa);
				return retval;
			}
973
974
975
976
977
		}
		else
		{
			new_wa->backup = NULL;
		}
oharboe's avatar
oharboe committed
978

979
980
981
		/* put new entry in list */
		*p = new_wa;
	}
oharboe's avatar
oharboe committed
982

983
984
985
	/* mark as used, and return the new (reused) area */
	new_wa->free = 0;
	*area = new_wa;
oharboe's avatar
oharboe committed
986

987
988
	/* user pointer */
	new_wa->user = area;
oharboe's avatar
oharboe committed
989

990
991
992
	return ERROR_OK;
}

oharboe's avatar
   
oharboe committed
993
int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore)
994
995
996
{
	if (area->free)
		return ERROR_OK;
oharboe's avatar
oharboe committed
997

oharboe's avatar
   
oharboe committed
998
	if (restore&&target->backup_working_area)
999
1000
	{
		int retval;
zwelch's avatar
zwelch committed
1001
		if((retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup)) != ERROR_OK)
1002
1003
			return retval;
	}
oharboe's avatar
oharboe committed
1004

1005
	area->free = 1;
oharboe's avatar
oharboe committed
1006

1007
1008
1009
	/* mark user pointer invalid */
	*area->user = NULL;
	area->user = NULL;
oharboe's avatar
oharboe committed
1010

1011
1012
1013
	return ERROR_OK;
}

oharboe's avatar
   
oharboe committed
1014
1015
1016
1017
1018
int target_free_working_area(struct target_s *target, working_area_t *area)
{
	return target_free_working_area_restore(target, area, 1);
}

1019
1020
1021
1022
/* free resources and restore memory, if restoring memory fails,
 * free up resources anyway
 */
void target_free_all_working_areas_restore(struct target_s *target, int restore)
1023
1024
1025
1026
1027
1028
{
	working_area_t *c = target->working_areas;

	while (c)
	{
		working_area_t *next = c->next;
oharboe's avatar
   
oharboe committed
1029
		target_free_working_area_restore(target, c, restore);
oharboe's avatar
oharboe committed
1030

1031
1032
		if (c->backup)
			free(c->backup);
oharboe's avatar
oharboe committed
1033

1034
		free(c);
oharboe's avatar
oharboe committed
1035

1036
1037
		c = next;
	}
oharboe's avatar
oharboe committed
1038

1039
1040
1041
	target->working_areas = NULL;
}

1042
void target_free_all_working_areas(struct target_s *target)
oharboe's avatar
   
oharboe committed
1043
{
1044
	target_free_all_working_areas_restore(target, 1);
oharboe's avatar
   
oharboe committed
1045
1046
}

1047
1048
int target_register_commands(struct command_context_s *cmd_ctx)
{
1049

oharboe's avatar
oharboe committed
1050
	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)");
1051

1052
1053
1054



1055
	register_jim(cmd_ctx, "target", jim_target, "configure target" );
1056

1057
1058
1059
1060
1061
1062
1063
1064
	return ERROR_OK;
}

int target_arch_state(struct target_s *target)
{
	int retval;
	if (target==NULL)
	{
1065
		LOG_USER("No target has been configured");
1066
1067
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
1068

1069
	LOG_USER("target state: %s",
1070
		 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
oharboe's avatar
oharboe committed
1071

1072
1073
	if (target->state!=TARGET_HALTED)
		return ERROR_OK;
oharboe's avatar
oharboe committed
1074

1075
1076
1077
1078
	retval=target->type->arch_state(target);
	return retval;
}

oharboe's avatar
oharboe committed
1079
1080
/* Single aligned words are guaranteed to use 16 or 32 bit access
 * mode respectively, otherwise data is handled as quickly as
1081
1082
1083
1084
1085
 * possible
 */
int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
{
	int retval;
1086
1087
	LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);

1088
	if (!target_was_examined(target))
1089
1090
1091
1092
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
1093

1094
1095
1096
1097
	if (size == 0) {
		return ERROR_OK;
	}

1098
	if ((address + size - 1) < address)
1099
1100
1101
1102
1103
	{
		/* GDB can request this when e.g. PC is 0xfffffffc*/
		LOG_ERROR("address+size wrapped(0x%08x, 0x%08x)", address, size);
		return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
1104

1105
1106
	if (((address % 2) == 0) && (size == 2))
	{
zwelch's avatar
zwelch committed
1107
		return target_write_memory(target, address, 2, 1, buffer);
1108
	}
oharboe's avatar
oharboe committed
1109

1110
1111
1112
	/* handle unaligned head bytes */
	if (address % 4)
	{
1113
		u32 unaligned = 4 - (address % 4);
oharboe's avatar
oharboe committed
1114

1115
1116
1117
		if (unaligned > size)
			unaligned = size;

zwelch's avatar
zwelch committed
1118
		if ((retval = target_write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
1119
			return retval;
oharboe's avatar
oharboe committed
1120

1121
1122
1123
1124
		buffer += unaligned;
		address += unaligned;
		size -= unaligned;
	}
oharboe's avatar
oharboe committed
1125

1126
1127
1128
1129
	/* handle aligned words */
	if (size >= 4)
	{
		int aligned = size - (size % 4);
oharboe's avatar
oharboe committed
1130

1131
1132
1133
1134
1135
1136
1137
1138
		/* use bulk writes above a certain limit. This may have to be changed */
		if (aligned > 128)
		{
			if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)
				return retval;
		}
		else
		{
zwelch's avatar
zwelch committed
1139
			if ((retval = target_write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
1140
1141
				return retval;
		}
oharboe's avatar
oharboe committed
1142

1143
1144
1145
1146
		buffer += aligned;
		address += aligned;
		size -= aligned;
	}
oharboe's avatar
oharboe committed
1147

1148
1149
1150
	/* handle tail writes of less than 4 bytes */
	if (size > 0)
	{
zwelch's avatar
zwelch committed
1151
		if ((retval = target_write_memory(target, address, 1, size, buffer)) != ERROR_OK)
1152
1153
			return retval;
	}
oharboe's avatar
oharboe committed
1154

1155
1156
1157
	return ERROR_OK;
}

oharboe's avatar
oharboe committed
1158
1159
/* Single aligned words are guaranteed to use 16 or 32 bit access
 * mode respectively, otherwise data is handled as quickly as
1160
1161
1162
1163
1164
 * possible
 */
int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
{
<