target.c 124 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007-2009 Ø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
 *   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

36
37
38
#include <helper/time_support.h>
#include <jtag/jtag.h>

39
#include "target.h"
40
#include "target_type.h"
41
#include "target_request.h"
42
#include "breakpoints.h"
43
44
45
#include "register.h"
#include "trace.h"
#include "image.h"
46
47


48
49
50
51
static int target_array2mem(Jim_Interp *interp, struct target *target,
		int argc, Jim_Obj *const *argv);
static int target_mem2array(Jim_Interp *interp, struct target *target,
		int argc, Jim_Obj *const *argv);
52

53
/* targets */
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
extern struct target_type arm7tdmi_target;
extern struct target_type arm720t_target;
extern struct target_type arm9tdmi_target;
extern struct target_type arm920t_target;
extern struct target_type arm966e_target;
extern struct target_type arm926ejs_target;
extern struct target_type fa526_target;
extern struct target_type feroceon_target;
extern struct target_type dragonite_target;
extern struct target_type xscale_target;
extern struct target_type cortexm3_target;
extern struct target_type cortexa8_target;
extern struct target_type arm11_target;
extern struct target_type mips_m4k_target;
extern struct target_type avr_target;
69
extern struct target_type dsp563xx_target;
Zachary T Welch's avatar
Zachary T Welch committed
70
extern struct target_type testee_target;
71
72

struct target_type *target_types[] =
73
74
75
76
77
78
79
{
	&arm7tdmi_target,
	&arm9tdmi_target,
	&arm920t_target,
	&arm720t_target,
	&arm966e_target,
	&arm926ejs_target,
80
	&fa526_target,
81
	&feroceon_target,
82
	&dragonite_target,
83
84
	&xscale_target,
	&cortexm3_target,
85
	&cortexa8_target,
oharboe's avatar
oharboe committed
86
	&arm11_target,
ntfreak's avatar
ntfreak committed
87
	&mips_m4k_target,
88
	&avr_target,
89
	&dsp563xx_target,
Zachary T Welch's avatar
Zachary T Welch committed
90
	&testee_target,
91
92
93
	NULL,
};

Zachary T Welch's avatar
Zachary T Welch committed
94
struct target *all_targets = NULL;
95
struct target_event_callback *target_event_callbacks = NULL;
96
struct target_timer_callback *target_timer_callbacks = NULL;
97

98
static const Jim_Nvp nvp_assert[] = {
99
100
101
102
103
104
105
	{ .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 }
106
107
};

108
static const Jim_Nvp nvp_error_target[] = {
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	{ .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 }
};

123
const char *target_strerror_safe(int err)
124
125
126
{
	const Jim_Nvp *n;

127
	n = Jim_Nvp_value2name_simple(nvp_error_target, err);
zwelch's avatar
zwelch committed
128
	if (n->name == NULL) {
129
130
131
132
133
134
		return "unknown";
	} else {
		return n->name;
	}
}

135
static const Jim_Nvp nvp_target_event[] = {
136
137
	{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
	{ .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
138

139
	{ .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
140
141
142
143
144
	{ .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" },

145
146
147
	{ .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
	{ .name = "gdb-end", .value = TARGET_EVENT_GDB_END },

148
	/* historical name */
149

150
	{ .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
151
152

	{ .value = TARGET_EVENT_RESET_ASSERT_PRE,    .name = "reset-assert-pre" },
153
	{ .value = TARGET_EVENT_RESET_ASSERT,        .name = "reset-assert" },
154
155
156
157
158
159
160
	{ .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" },
161
162
	{ .value = TARGET_EVENT_RESET_INIT,          .name = "reset-init" },
	{ .value = TARGET_EVENT_RESET_END,           .name = "reset-end" },
163

164
	{ .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
165
	{ .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
166

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
	{ .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 }
184
185
};

186
static const Jim_Nvp nvp_target_state[] = {
187
188
189
190
191
192
	{ .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 },
193
194
};

195
static const Jim_Nvp nvp_target_debug_reason [] = {
196
197
198
199
200
201
202
203
204
205
	{ .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 },
};

206
static const Jim_Nvp nvp_target_endian[] = {
207
208
209
	{ .name = "big",    .value = TARGET_BIG_ENDIAN },
	{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
	{ .name = "be",     .value = TARGET_BIG_ENDIAN },
210
	{ .name = "le",     .value = TARGET_LITTLE_ENDIAN },
211
212
213
	{ .name = NULL,     .value = -1 },
};

214
static const Jim_Nvp nvp_reset_modes[] = {
215
216
217
218
219
220
221
	{ .name = "unknown", .value = RESET_UNKNOWN },
	{ .name = "run"    , .value = RESET_RUN },
	{ .name = "halt"   , .value = RESET_HALT },
	{ .name = "init"   , .value = RESET_INIT },
	{ .name = NULL     , .value = -1 },
};

222
223
224
225
226
227
228
229
230
231
232
233
234
const char *debug_reason_name(struct target *t)
{
	const char *cp;

	cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason,
			t->debug_reason)->name;
	if (!cp) {
		LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason));
		cp = "(*BUG*unknown*BUG*)";
	}
	return cp;
}

235
const char *
Zachary T Welch's avatar
Zachary T Welch committed
236
target_state_name( struct target *t )
237
238
239
240
241
242
243
244
245
246
{
	const char *cp;
	cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name;
	if( !cp ){
		LOG_ERROR("Invalid target state: %d", (int)(t->state));
		cp = "(*BUG*unknown*BUG*)";
	}
	return cp;
}

247
/* determine the number of the new target */
248
static int new_target_number(void)
249
{
Zachary T Welch's avatar
Zachary T Welch committed
250
	struct target *t;
251
252
253
254
255
	int x;

	/* number is 0 based */
	x = -1;
	t = all_targets;
zwelch's avatar
zwelch committed
256
257
	while (t) {
		if (x < t->target_number) {
258
259
260
261
			x = t->target_number;
		}
		t = t->next;
	}
zwelch's avatar
zwelch committed
262
	return x + 1;
263
264
}

265
/* read a uint32_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
266
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
267
268
269
270
271
272
273
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u32(buffer);
	else
		return be_to_h_u32(buffer);
}

zwelch's avatar
zwelch committed
274
/* read a uint16_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
275
uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
276
277
278
279
280
281
282
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u16(buffer);
	else
		return be_to_h_u16(buffer);
}

283
/* read a uint8_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
284
uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer)
285
286
287
288
{
	return *buffer & 0x0ff;
}

289
/* write a uint32_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
290
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
291
292
293
294
295
296
297
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u32_to_le(buffer, value);
	else
		h_u32_to_be(buffer, value);
}

zwelch's avatar
zwelch committed
298
/* write a uint16_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
299
void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
300
301
302
303
304
305
306
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u16_to_le(buffer, value);
	else
		h_u16_to_be(buffer, value);
}

307
/* write a uint8_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
308
void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value)
309
310
311
312
{
	*buffer = value;
}

313
/* return a pointer to a configured target; id is name or number */
Zachary T Welch's avatar
Zachary T Welch committed
314
struct target *get_target(const char *id)
315
{
Zachary T Welch's avatar
Zachary T Welch committed
316
	struct target *target;
317
318
319
320
321
322
323
324
325

	/* 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;
	}

326
327
	/* It's OK to remove this fallback sometime after August 2010 or so */

328
	/* no match, try as number */
329
330
	unsigned num;
	if (parse_uint(id, &num) != ERROR_OK)
331
332
333
		return NULL;

	for (target = all_targets; target; target = target->next) {
334
335
336
		if (target->target_number == (int)num) {
			LOG_WARNING("use '%s' as target identifier, not '%u'",
					target->cmd_name, num);
337
			return target;
338
		}
339
340
341
342
343
	}

	return NULL;
}

344
/* returns a pointer to the n-th configured target */
Zachary T Welch's avatar
Zachary T Welch committed
345
static struct target *get_target_by_num(int num)
346
{
Zachary T Welch's avatar
Zachary T Welch committed
347
	struct target *target = all_targets;
348

zwelch's avatar
zwelch committed
349
350
	while (target) {
		if (target->target_number == num) {
351
			return target;
352
		}
353
354
355
356
357
358
		target = target->next;
	}

	return NULL;
}

359
struct target* get_current_target(struct command_context *cmd_ctx)
360
{
Zachary T Welch's avatar
Zachary T Welch committed
361
	struct target *target = get_target_by_num(cmd_ctx->current_target);
oharboe's avatar
oharboe committed
362

363
364
	if (target == NULL)
	{
365
		LOG_ERROR("BUG: current_target out of bounds");
366
367
368
		exit(-1);
	}

oharboe's avatar
oharboe committed
369
	return target;
370
371
}

Zachary T Welch's avatar
Zachary T Welch committed
372
int target_poll(struct target *target)
373
{
374
375
	int retval;

376
	/* We can't poll until after examine */
377
	if (!target_was_examined(target))
378
379
380
381
	{
		/* Fail silently lest we pollute the log */
		return ERROR_FAIL;
	}
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404

	retval = target->type->poll(target);
	if (retval != ERROR_OK)
		return retval;

	if (target->halt_issued)
	{
		if (target->state == TARGET_HALTED)
		{
			target->halt_issued = false;
		} else
		{
			long long t = timeval_ms() - target->halt_issued_time;
			if (t>1000)
			{
				target->halt_issued = false;
				LOG_INFO("Halt timed out, wake up GDB.");
				target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
			}
		}
	}

	return ERROR_OK;
405
406
}

Zachary T Welch's avatar
Zachary T Welch committed
407
int target_halt(struct target *target)
408
{
409
	int retval;
410
	/* We can't poll until after examine */
411
	if (!target_was_examined(target))
412
413
414
415
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
416
417
418
419
420
421
422
423
424

	retval = target->type->halt(target);
	if (retval != ERROR_OK)
		return retval;

	target->halt_issued = true;
	target->halt_issued_time = timeval_ms();

	return ERROR_OK;
425
426
}

Zachary T Welch's avatar
Zachary T Welch committed
427
int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
428
{
429
	int retval;
oharboe's avatar
oharboe committed
430

431
	/* We can't poll until after examine */
432
	if (!target_was_examined(target))
433
434
435
436
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
437

oharboe's avatar
oharboe committed
438
439
440
441
	/* 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.
	 */
442
443
	if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
444

445
	return retval;
446
447
}

448
int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode)
449
450
{
	char buf[100];
451
	int retval;
452
	Jim_Nvp *n;
453
	n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode);
zwelch's avatar
zwelch committed
454
	if (n->name == NULL) {
455
456
457
458
		LOG_ERROR("invalid reset mode");
		return ERROR_FAIL;
	}

459
460
461
462
	/* 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.
	 */
463
464
465
	bool save_poll = jtag_poll_get_enabled();

	jtag_poll_set_enabled(false);
466

467
	sprintf(buf, "ocd_process_reset %s", n->name);
468
	retval = Jim_Eval(cmd_ctx->interp, buf);
469

470
	jtag_poll_set_enabled(save_poll);
471

zwelch's avatar
zwelch committed
472
	if (retval != JIM_OK) {
473
		Jim_PrintErrorMessage(cmd_ctx->interp);
474
475
		return ERROR_FAIL;
	}
476
477

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

Øyvind Harboe's avatar
Øyvind Harboe committed
480
481
482
483
484
	struct target *target;
	for (target = all_targets; target; target = target->next) {
		target->type->check_reset(target);
	}

485
	return retval;
486
487
}

Zachary T Welch's avatar
Zachary T Welch committed
488
static int identity_virt2phys(struct target *target,
David Brownell's avatar
David Brownell committed
489
		uint32_t virtual, uint32_t *physical)
490
491
492
493
494
{
	*physical = virtual;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
495
static int no_mmu(struct target *target, int *enabled)
496
{
497
	*enabled = 0;
498
499
500
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
501
static int default_examine(struct target *target)
502
{
503
	target_set_examined(target);
504
505
506
	return ERROR_OK;
}

Øyvind Harboe's avatar
Øyvind Harboe committed
507
508
509
510
511
512
/* no check by default */
static int default_check_reset(struct target *target)
{
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
513
int target_examine_one(struct target *target)
zwelch's avatar
zwelch committed
514
515
516
517
{
	return target->type->examine(target);
}

zwelch's avatar
zwelch committed
518
519
static int jtag_enable_callback(enum jtag_event event, void *priv)
{
Zachary T Welch's avatar
Zachary T Welch committed
520
	struct target *target = priv;
zwelch's avatar
zwelch committed
521
522
523
524
525
526
527
528
529

	if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled)
		return ERROR_OK;

	jtag_unregister_event_callback(jtag_enable_callback, target);
	return target_examine_one(target);
}


zwelch's avatar
zwelch committed
530
/* Targets that correctly implement init + examine, i.e.
531
 * no communication with target during init:
oharboe's avatar
oharboe committed
532
533
 *
 * XScale
534
 */
ntfreak's avatar
ntfreak committed
535
int target_examine(void)
536
537
{
	int retval = ERROR_OK;
Zachary T Welch's avatar
Zachary T Welch committed
538
	struct target *target;
zwelch's avatar
zwelch committed
539
540

	for (target = all_targets; target; target = target->next)
541
	{
zwelch's avatar
zwelch committed
542
543
544
545
		/* defer examination, but don't skip it */
		if (!target->tap->enabled) {
			jtag_register_event_callback(jtag_enable_callback,
					target);
zwelch's avatar
zwelch committed
546
			continue;
zwelch's avatar
zwelch committed
547
		}
zwelch's avatar
zwelch committed
548
		if ((retval = target_examine_one(target)) != ERROR_OK)
549
550
551
552
			return retval;
	}
	return retval;
}
553
const char *target_type_name(struct target *target)
zwelch's avatar
zwelch committed
554
555
556
{
	return target->type->name;
}
557

Zachary T Welch's avatar
Zachary T Welch committed
558
static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
559
{
560
	if (!target_was_examined(target))
561
562
563
564
565
566
567
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->write_memory_imp(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
568
static int target_read_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
569
{
570
	if (!target_was_examined(target))
571
572
573
574
575
576
577
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->read_memory_imp(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
578
static int target_soft_reset_halt_imp(struct target *target)
579
{
580
	if (!target_was_examined(target))
581
582
583
584
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
585
586
	if (!target->type->soft_reset_halt_imp) {
		LOG_ERROR("Target %s does not support soft_reset_halt",
587
				target_name(target));
588
589
		return ERROR_FAIL;
	}
590
591
592
	return target->type->soft_reset_halt_imp(target);
}

Zachary T Welch's avatar
Zachary T Welch committed
593
static int target_run_algorithm_imp(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
594
{
595
	if (!target_was_examined(target))
596
597
598
599
600
601
	{
		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);
}
602

Zachary T Welch's avatar
Zachary T Welch committed
603
int target_read_memory(struct target *target,
604
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
605
606
607
608
{
	return target->type->read_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
609
int target_read_phys_memory(struct target *target,
610
611
612
613
614
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target->type->read_phys_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
615
int target_write_memory(struct target *target,
616
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
617
618
619
{
	return target->type->write_memory(target, address, size, count, buffer);
}
620

Zachary T Welch's avatar
Zachary T Welch committed
621
int target_write_phys_memory(struct target *target,
622
623
624
625
626
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target->type->write_phys_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
627
int target_bulk_write_memory(struct target *target,
628
		uint32_t address, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
629
630
631
632
{
	return target->type->bulk_write_memory(target, address, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
633
int target_add_breakpoint(struct target *target,
634
		struct breakpoint *breakpoint)
635
{
636
637
638
639
	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target %s is not halted", target->cmd_name);
		return ERROR_TARGET_NOT_HALTED;
	}
640
641
	return target->type->add_breakpoint(target, breakpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
642
int target_remove_breakpoint(struct target *target,
643
		struct breakpoint *breakpoint)
644
645
646
647
{
	return target->type->remove_breakpoint(target, breakpoint);
}

Zachary T Welch's avatar
Zachary T Welch committed
648
int target_add_watchpoint(struct target *target,
649
		struct watchpoint *watchpoint)
650
{
651
652
653
654
	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target %s is not halted", target->cmd_name);
		return ERROR_TARGET_NOT_HALTED;
	}
655
656
	return target->type->add_watchpoint(target, watchpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
657
int target_remove_watchpoint(struct target *target,
658
		struct watchpoint *watchpoint)
659
660
661
{
	return target->type->remove_watchpoint(target, watchpoint);
}
zwelch's avatar
zwelch committed
662

Zachary T Welch's avatar
Zachary T Welch committed
663
int target_get_gdb_reg_list(struct target *target,
Zachary T Welch's avatar
Zachary T Welch committed
664
		struct reg **reg_list[], int *reg_list_size)
zwelch's avatar
zwelch committed
665
666
667
{
	return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
}
Zachary T Welch's avatar
Zachary T Welch committed
668
int target_step(struct target *target,
669
		int current, uint32_t address, int handle_breakpoints)
zwelch's avatar
zwelch committed
670
671
672
673
{
	return target->type->step(target, current, address, handle_breakpoints);
}

zwelch's avatar
zwelch committed
674

Zachary T Welch's avatar
Zachary T Welch committed
675
int target_run_algorithm(struct target *target,
676
		int num_mem_params, struct mem_param *mem_params,
677
		int num_reg_params, struct reg_param *reg_param,
678
		uint32_t entry_point, uint32_t exit_point,
zwelch's avatar
zwelch committed
679
680
681
682
683
684
685
		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);
}

686
687
688
689
690
/**
 * Reset the @c examined flag for the given target.
 * Pure paranoia -- targets are zeroed on allocation.
 */
static void target_reset_examined(struct target *target)
691
{
692
	target->examined = false;
693
694
}

695
static int
Zachary T Welch's avatar
Zachary T Welch committed
696
err_read_phys_memory(struct target *target, uint32_t address,
697
		uint32_t size, uint32_t count, uint8_t *buffer)
698
{
699
	LOG_ERROR("Not implemented: %s", __func__);
700
	return ERROR_FAIL;
701
702
}

703
static int
Zachary T Welch's avatar
Zachary T Welch committed
704
err_write_phys_memory(struct target *target, uint32_t address,
705
		uint32_t size, uint32_t count, uint8_t *buffer)
706
{
707
	LOG_ERROR("Not implemented: %s", __func__);
708
	return ERROR_FAIL;
709
710
}

711
712
static int handle_target(void *priv);

713
714
static int target_init_one(struct command_context *cmd_ctx,
		struct target *target)
715
{
716
	target_reset_examined(target);
oharboe's avatar
oharboe committed
717

718
719
720
	struct target_type *type = target->type;
	if (type->examine == NULL)
		type->examine = default_examine;
721

Øyvind Harboe's avatar
Øyvind Harboe committed
722
723
724
	if (type->check_reset== NULL)
		type->check_reset = default_check_reset;

725
726
727
728
729
730
	int retval = type->init_target(cmd_ctx, target);
	if (ERROR_OK != retval)
	{
		LOG_ERROR("target '%s' init failed", target_name(target));
		return retval;
	}
oharboe's avatar
oharboe committed
731

732
733
734
735
736
737
738
739
740
741
	/**
	 * @todo get rid of those *memory_imp() methods, now that all
	 * callers are using target_*_memory() accessors ... and make
	 * sure the "physical" paths handle the same issues.
	 */
	/* a non-invasive way(in terms of patches) to add some code that
	 * runs before the type->write/read_memory implementation
	 */
	type->write_memory_imp = target->type->write_memory;
	type->write_memory = target_write_memory_imp;
oharboe's avatar
oharboe committed
742

743
744
	type->read_memory_imp = target->type->read_memory;
	type->read_memory = target_read_memory_imp;
745

746
747
	type->soft_reset_halt_imp = target->type->soft_reset_halt;
	type->soft_reset_halt = target_soft_reset_halt_imp;
David Brownell's avatar
David Brownell committed
748

749
750
	type->run_algorithm_imp = target->type->run_algorithm;
	type->run_algorithm = target_run_algorithm_imp;
751

752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
	/* Sanity-check MMU support ... stub in what we must, to help
	 * implement it in stages, but warn if we need to do so.
	 */
	if (type->mmu)
	{
		if (type->write_phys_memory == NULL)
		{
			LOG_ERROR("type '%s' is missing write_phys_memory",
					type->name);
			type->write_phys_memory = err_write_phys_memory;
		}
		if (type->read_phys_memory == NULL)
		{
			LOG_ERROR("type '%s' is missing read_phys_memory",
					type->name);
			type->read_phys_memory = err_read_phys_memory;
		}
		if (type->virt2phys == NULL)
		{
			LOG_ERROR("type '%s' is missing virt2phys", type->name);
			type->virt2phys = identity_virt2phys;
		}
	}
	else
	{
777
778
779
780
		/* Make sure no-MMU targets all behave the same:  make no
		 * distinction between physical and virtual addresses, and
		 * ensure that virt2phys() is always an identity mapping.
		 */
781
782
783
784
		if (type->write_phys_memory || type->read_phys_memory
				|| type->virt2phys)
		{
			LOG_WARNING("type '%s' has bad MMU hooks", type->name);
785
		}
786
787
788
789
790

		type->mmu = no_mmu;
		type->write_phys_memory = type->write_memory;
		type->read_phys_memory = type->read_memory;
		type->virt2phys = identity_virt2phys;
791
	}
792
793
	return ERROR_OK;
}
oharboe's avatar
oharboe committed
794

795
796
797
798
799
800
int target_init(struct command_context *cmd_ctx)
{
	struct target *target;
	int retval;

	for (target = all_targets; target; target = target->next)
801
	{
802
803
		retval = target_init_one(cmd_ctx, target);
		if (ERROR_OK != retval)
804
			return retval;
805
	}
oharboe's avatar
oharboe committed
806

807
808
809
810
811
812
813
814
815
816
817
818
	if (!all_targets)
		return ERROR_OK;

	retval = target_register_user_commands(cmd_ctx);
	if (ERROR_OK != retval)
		return retval;

	retval = target_register_timer_callback(&handle_target,
			100, 1, cmd_ctx->interp);
	if (ERROR_OK != retval)
		return retval;

819
820
821
	return ERROR_OK;
}

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
COMMAND_HANDLER(handle_target_init_command)
{
	if (CMD_ARGC != 0)
		return ERROR_COMMAND_SYNTAX_ERROR;

	static bool target_initialized = false;
	if (target_initialized)
	{
		LOG_INFO("'target init' has already been called");
		return ERROR_OK;
	}
	target_initialized = true;

	LOG_DEBUG("Initializing targets...");
	return target_init(CMD_CTX);
}

Zachary T Welch's avatar
Zachary T Welch committed
839
int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
840
{
841
	struct target_event_callback **callbacks_p = &target_event_callbacks;
oharboe's avatar
oharboe committed
842

843
844
845
846
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
847

848
849
850
851
852
853
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
854

855
	(*callbacks_p) = malloc(sizeof(struct target_event_callback));
856
857
858
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
859

860
861
862
863
864
	return ERROR_OK;
}

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

868
869
870
871
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
872

873
874
875
876
877
878
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
879

880
	(*callbacks_p) = malloc(sizeof(struct target_timer_callback));
881
882
883
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->periodic = periodic;
	(*callbacks_p)->time_ms = time_ms;
oharboe's avatar
oharboe committed
884

885
886
887
888
889
890
891
892
893
	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
894

895
896
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
897

898
899
900
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
901
int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
902
{
903
904
	struct target_event_callback **p = &target_event_callbacks;
	struct target_event_callback *c = target_event_callbacks;
oharboe's avatar
oharboe committed
905

906
907
908
909
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
910

911
912
	while (c)
	{
913
		struct target_event_callback *next = c->next;
914
915
916
917
918
919
920
921
922
923
		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
924

925
926
927
928
929
	return ERROR_OK;
}

int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
{
930
931
	struct target_timer_callback **p = &target_timer_callbacks;
	struct target_timer_callback *c = target_timer_callbacks;
oharboe's avatar
oharboe committed
932

933
934
935
936
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
937

938
939
	while (c)
	{
940
		struct target_timer_callback *next = c->next;
941
942
943
944
945
946
947
948
949
950
		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
951

952
953
954
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
955
int target_call_event_callbacks(struct target *target, enum target_event event)
956
{
957
958
	struct target_event_callback *callback = target_event_callbacks;
	struct target_event_callback *next_callback;
oharboe's avatar
oharboe committed
959

960
961
962
	if (event == TARGET_EVENT_HALTED)
	{
		/* execute early halted first */
963
		target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
964
965
	}

966
967
	LOG_DEBUG("target event %i (%s)",
			  event,
968
			  Jim_Nvp_value2name_simple(nvp_target_event, event)->name);
oharboe's avatar
oharboe committed
969

970
	target_handle_event(target, event);
971

972
973
974
975
976
977
	while (callback)
	{
		next_callback = callback->next;
		callback->callback(target, event, callback->priv);
		callback = next_callback;
	}
oharboe's avatar
oharboe committed
978

979
980
981
	return ERROR_OK;
}

982
static int target_timer_callback_periodic_restart(
983
		struct target_timer_callback *cb, struct timeval *now)
984
{
985
986
987
988
989
990
991
992
993
994
995
996
	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;
}

997
static int target_call_timer_callback(struct target_timer_callback *cb,
998
999
1000
		struct timeval *now)
{
	cb->callback(cb->priv);
1001

1002
1003
1004
1005
1006
1007
1008
1009
	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
1010
1011
	keep_alive();

1012
	struct timeval now;
1013
	gettimeofday(&now, NULL);
oharboe's avatar
oharboe committed
1014