target.c 118 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
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
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
47

Zachary T Welch's avatar
Zachary T Welch committed
48
49
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);
50

51
/* targets */
52
53
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;

struct target_type *target_types[] =
69
70
71
72
73
74
75
{
	&arm7tdmi_target,
	&arm9tdmi_target,
	&arm920t_target,
	&arm720t_target,
	&arm966e_target,
	&arm926ejs_target,
76
	&fa526_target,
77
	&feroceon_target,
78
	&dragonite_target,
79
80
	&xscale_target,
	&cortexm3_target,
81
	&cortexa8_target,
oharboe's avatar
oharboe committed
82
	&arm11_target,
ntfreak's avatar
ntfreak committed
83
	&mips_m4k_target,
84
	&avr_target,
85
86
87
	NULL,
};

Zachary T Welch's avatar
Zachary T Welch committed
88
struct target *all_targets = NULL;
89
struct target_event_callback *target_event_callbacks = NULL;
90
struct target_timer_callback *target_timer_callbacks = NULL;
91

92
93
94
95
96
97
98
99
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 }
100
101
};

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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 }
};

117
const char *target_strerror_safe(int err)
118
119
120
{
	const Jim_Nvp *n;

121
	n = Jim_Nvp_value2name_simple(nvp_error_target, err);
zwelch's avatar
zwelch committed
122
	if (n->name == NULL) {
123
124
125
126
127
128
		return "unknown";
	} else {
		return n->name;
	}
}

129
static const Jim_Nvp nvp_target_event[] = {
130
131
	{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
	{ .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
132

133
	{ .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
134
135
136
137
138
	{ .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" },

139
140
141
	{ .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
	{ .name = "gdb-end", .value = TARGET_EVENT_GDB_END },

142
	/* historical name */
143

144
	{ .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
145
146
147
148
149
150
151
152
153

	{ .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" },
154
155
156
	{ .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" },
	{ .value = TARGET_EVENT_RESET_END, .name = "reset-end" },

157
	{ .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
158
	{ .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	{ .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 }
177
178
};

179
180
181
182
183
184
185
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 },
186
187
};

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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 },
203
	{ .name = "le",     .value = TARGET_LITTLE_ENDIAN },
204
205
206
	{ .name = NULL,     .value = -1 },
};

207
208
209
210
211
212
213
214
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 },
};

215
const char *
Zachary T Welch's avatar
Zachary T Welch committed
216
target_state_name( struct target *t )
217
218
219
220
221
222
223
224
225
226
{
	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;
}

227
/* determine the number of the new target */
228
static int new_target_number(void)
229
{
Zachary T Welch's avatar
Zachary T Welch committed
230
	struct target *t;
231
232
233
234
235
	int x;

	/* number is 0 based */
	x = -1;
	t = all_targets;
zwelch's avatar
zwelch committed
236
237
	while (t) {
		if (x < t->target_number) {
238
239
240
241
			x = t->target_number;
		}
		t = t->next;
	}
zwelch's avatar
zwelch committed
242
	return x + 1;
243
244
}

245
/* read a uint32_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
246
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
247
248
249
250
251
252
253
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u32(buffer);
	else
		return be_to_h_u32(buffer);
}

zwelch's avatar
zwelch committed
254
/* read a uint16_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
255
uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
256
257
258
259
260
261
262
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u16(buffer);
	else
		return be_to_h_u16(buffer);
}

263
/* read a uint8_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
264
uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer)
265
266
267
268
{
	return *buffer & 0x0ff;
}

269
/* write a uint32_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
270
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
271
272
273
274
275
276
277
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u32_to_le(buffer, value);
	else
		h_u32_to_be(buffer, value);
}

zwelch's avatar
zwelch committed
278
/* write a uint16_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
279
void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
280
281
282
283
284
285
286
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u16_to_le(buffer, value);
	else
		h_u16_to_be(buffer, value);
}

287
/* write a uint8_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
288
void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value)
289
290
291
292
{
	*buffer = value;
}

293
/* return a pointer to a configured target; id is name or number */
Zachary T Welch's avatar
Zachary T Welch committed
294
struct target *get_target(const char *id)
295
{
Zachary T Welch's avatar
Zachary T Welch committed
296
	struct target *target;
297
298
299
300
301
302
303
304
305

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

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

308
	/* no match, try as number */
309
310
	unsigned num;
	if (parse_uint(id, &num) != ERROR_OK)
311
312
313
		return NULL;

	for (target = all_targets; target; target = target->next) {
314
315
316
		if (target->target_number == (int)num) {
			LOG_WARNING("use '%s' as target identifier, not '%u'",
					target->cmd_name, num);
317
			return target;
318
		}
319
320
321
322
323
	}

	return NULL;
}

324
/* returns a pointer to the n-th configured target */
Zachary T Welch's avatar
Zachary T Welch committed
325
static struct target *get_target_by_num(int num)
326
{
Zachary T Welch's avatar
Zachary T Welch committed
327
	struct target *target = all_targets;
328

zwelch's avatar
zwelch committed
329
330
	while (target) {
		if (target->target_number == num) {
331
			return target;
332
		}
333
334
335
336
337
338
		target = target->next;
	}

	return NULL;
}

339
struct target* get_current_target(struct command_context *cmd_ctx)
340
{
Zachary T Welch's avatar
Zachary T Welch committed
341
	struct target *target = get_target_by_num(cmd_ctx->current_target);
oharboe's avatar
oharboe committed
342

343
344
	if (target == NULL)
	{
345
		LOG_ERROR("BUG: current_target out of bounds");
346
347
348
		exit(-1);
	}

oharboe's avatar
oharboe committed
349
	return target;
350
351
}

Zachary T Welch's avatar
Zachary T Welch committed
352
int target_poll(struct target *target)
353
{
354
355
	int retval;

356
	/* We can't poll until after examine */
357
	if (!target_was_examined(target))
358
359
360
361
	{
		/* Fail silently lest we pollute the log */
		return ERROR_FAIL;
	}
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

	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;
385
386
}

Zachary T Welch's avatar
Zachary T Welch committed
387
int target_halt(struct target *target)
388
{
389
	int retval;
390
	/* We can't poll until after examine */
391
	if (!target_was_examined(target))
392
393
394
395
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
396
397
398
399
400
401
402
403
404

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

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

	return ERROR_OK;
405
406
}

Zachary T Welch's avatar
Zachary T Welch committed
407
int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
408
{
409
	int retval;
oharboe's avatar
oharboe committed
410

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

oharboe's avatar
oharboe committed
418
419
420
421
	/* 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.
	 */
422
423
	if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
424

425
	return retval;
426
427
}

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

439
440
441
442
	/* 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.
	 */
443
444
445
	bool save_poll = jtag_poll_get_enabled();

	jtag_poll_set_enabled(false);
446

447
448
	sprintf(buf, "ocd_process_reset %s", n->name);
	retval = Jim_Eval(interp, buf);
449

450
	jtag_poll_set_enabled(save_poll);
451

zwelch's avatar
zwelch committed
452
	if (retval != JIM_OK) {
453
		Jim_PrintErrorMessage(interp);
454
455
		return ERROR_FAIL;
	}
456
457

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

460
	return retval;
461
462
}

Zachary T Welch's avatar
Zachary T Welch committed
463
static int identity_virt2phys(struct target *target,
David Brownell's avatar
David Brownell committed
464
		uint32_t virtual, uint32_t *physical)
465
466
467
468
469
{
	*physical = virtual;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
470
static int no_mmu(struct target *target, int *enabled)
471
{
472
	*enabled = 0;
473
474
475
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
476
static int default_examine(struct target *target)
477
{
478
	target_set_examined(target);
479
480
481
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
482
int target_examine_one(struct target *target)
zwelch's avatar
zwelch committed
483
484
485
486
{
	return target->type->examine(target);
}

zwelch's avatar
zwelch committed
487
488
static int jtag_enable_callback(enum jtag_event event, void *priv)
{
Zachary T Welch's avatar
Zachary T Welch committed
489
	struct target *target = priv;
zwelch's avatar
zwelch committed
490
491
492
493
494
495
496
497
498

	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
499
/* Targets that correctly implement init + examine, i.e.
500
 * no communication with target during init:
oharboe's avatar
oharboe committed
501
502
 *
 * XScale
503
 */
ntfreak's avatar
ntfreak committed
504
int target_examine(void)
505
506
{
	int retval = ERROR_OK;
Zachary T Welch's avatar
Zachary T Welch committed
507
	struct target *target;
zwelch's avatar
zwelch committed
508
509

	for (target = all_targets; target; target = target->next)
510
	{
zwelch's avatar
zwelch committed
511
512
513
514
		/* defer examination, but don't skip it */
		if (!target->tap->enabled) {
			jtag_register_event_callback(jtag_enable_callback,
					target);
zwelch's avatar
zwelch committed
515
			continue;
zwelch's avatar
zwelch committed
516
		}
zwelch's avatar
zwelch committed
517
		if ((retval = target_examine_one(target)) != ERROR_OK)
518
519
520
521
			return retval;
	}
	return retval;
}
Zachary T Welch's avatar
Zachary T Welch committed
522
const char *target_get_name(struct target *target)
zwelch's avatar
zwelch committed
523
524
525
{
	return target->type->name;
}
526

Zachary T Welch's avatar
Zachary T Welch committed
527
static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
528
{
529
	if (!target_was_examined(target))
530
531
532
533
534
535
536
	{
		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
537
static int target_read_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
538
{
539
	if (!target_was_examined(target))
540
541
542
543
544
545
546
	{
		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
547
static int target_soft_reset_halt_imp(struct target *target)
548
{
549
	if (!target_was_examined(target))
550
551
552
553
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
554
555
556
557
558
	if (!target->type->soft_reset_halt_imp) {
		LOG_ERROR("Target %s does not support soft_reset_halt",
				target->cmd_name);
		return ERROR_FAIL;
	}
559
560
561
	return target->type->soft_reset_halt_imp(target);
}

Zachary T Welch's avatar
Zachary T Welch committed
562
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)
563
{
564
	if (!target_was_examined(target))
565
566
567
568
569
570
	{
		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);
}
571

Zachary T Welch's avatar
Zachary T Welch committed
572
int target_read_memory(struct target *target,
573
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
574
575
576
577
{
	return target->type->read_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
578
int target_read_phys_memory(struct target *target,
579
580
581
582
583
		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
584
int target_write_memory(struct target *target,
585
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
586
587
588
{
	return target->type->write_memory(target, address, size, count, buffer);
}
589

Zachary T Welch's avatar
Zachary T Welch committed
590
int target_write_phys_memory(struct target *target,
591
592
593
594
595
		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
596
int target_bulk_write_memory(struct target *target,
597
		uint32_t address, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
598
599
600
601
{
	return target->type->bulk_write_memory(target, address, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
602
int target_add_breakpoint(struct target *target,
603
		struct breakpoint *breakpoint)
604
605
606
{
	return target->type->add_breakpoint(target, breakpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
607
int target_remove_breakpoint(struct target *target,
608
		struct breakpoint *breakpoint)
609
610
611
612
{
	return target->type->remove_breakpoint(target, breakpoint);
}

Zachary T Welch's avatar
Zachary T Welch committed
613
int target_add_watchpoint(struct target *target,
614
		struct watchpoint *watchpoint)
615
616
617
{
	return target->type->add_watchpoint(target, watchpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
618
int target_remove_watchpoint(struct target *target,
619
		struct watchpoint *watchpoint)
620
621
622
{
	return target->type->remove_watchpoint(target, watchpoint);
}
zwelch's avatar
zwelch committed
623

Zachary T Welch's avatar
Zachary T Welch committed
624
int target_get_gdb_reg_list(struct target *target,
Zachary T Welch's avatar
Zachary T Welch committed
625
		struct reg **reg_list[], int *reg_list_size)
zwelch's avatar
zwelch committed
626
627
628
{
	return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
}
Zachary T Welch's avatar
Zachary T Welch committed
629
int target_step(struct target *target,
630
		int current, uint32_t address, int handle_breakpoints)
zwelch's avatar
zwelch committed
631
632
633
634
{
	return target->type->step(target, current, address, handle_breakpoints);
}

zwelch's avatar
zwelch committed
635

Zachary T Welch's avatar
Zachary T Welch committed
636
int target_run_algorithm(struct target *target,
637
		int num_mem_params, struct mem_param *mem_params,
638
		int num_reg_params, struct reg_param *reg_param,
639
		uint32_t entry_point, uint32_t exit_point,
zwelch's avatar
zwelch committed
640
641
642
643
644
645
646
		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);
}

647
648
649
650
651
/**
 * Reset the @c examined flag for the given target.
 * Pure paranoia -- targets are zeroed on allocation.
 */
static void target_reset_examined(struct target *target)
652
{
653
	target->examined = false;
654
655
}

zwelch's avatar
zwelch committed
656

657

Zachary T Welch's avatar
Zachary T Welch committed
658
static int default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
659
{
660
	LOG_ERROR("Not implemented: %s", __func__);
661
662
663
	return ERROR_FAIL;
}

Zachary T Welch's avatar
Zachary T Welch committed
664
static int default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
665
{
666
	LOG_ERROR("Not implemented: %s", __func__);
667
668
669
	return ERROR_FAIL;
}

Zachary T Welch's avatar
Zachary T Welch committed
670
static int arm_cp_check(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm)
671
672
673
674
675
676
677
678
679
680
681
682
683
684
{
	/* basic check */
	if (!target_was_examined(target))
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}

	if ((cpnum <0) || (cpnum > 15))
	{
		LOG_ERROR("Illegal co-processor %d", cpnum);
		return ERROR_FAIL;
	}

685
	if (op1 > 7)
686
687
688
689
690
	{
		LOG_ERROR("Illegal op1");
		return ERROR_FAIL;
	}

691
	if (op2 > 7)
692
693
694
695
696
	{
		LOG_ERROR("Illegal op2");
		return ERROR_FAIL;
	}

697
	if (CRn > 15)
698
699
700
701
702
	{
		LOG_ERROR("Illegal CRn");
		return ERROR_FAIL;
	}

703
	if (CRm > 15)
704
705
706
707
708
	{
		LOG_ERROR("Illegal CRm");
		return ERROR_FAIL;
	}

709
710
711
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
712
int target_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
713
714
715
716
717
718
719
720
721
722
{
	int retval;

	retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
	if (retval != ERROR_OK)
		return retval;

	return target->type->mrc(target, cpnum, op1, op2, CRn, CRm, value);
}

Zachary T Welch's avatar
Zachary T Welch committed
723
int target_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
724
725
726
727
728
729
730
731
732
733
{
	int retval;

	retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
	if (retval != ERROR_OK)
		return retval;

	return target->type->mcr(target, cpnum, op1, op2, CRn, CRm, value);
}

734
static int
Zachary T Welch's avatar
Zachary T Welch committed
735
err_read_phys_memory(struct target *target, uint32_t address,
736
		uint32_t size, uint32_t count, uint8_t *buffer)
737
{
738
	LOG_ERROR("Not implemented: %s", __func__);
739
	return ERROR_FAIL;
740
741
}

742
static int
Zachary T Welch's avatar
Zachary T Welch committed
743
err_write_phys_memory(struct target *target, uint32_t address,
744
		uint32_t size, uint32_t count, uint8_t *buffer)
745
{
746
	LOG_ERROR("Not implemented: %s", __func__);
747
	return ERROR_FAIL;
748
749
}

750
int target_init(struct command_context *cmd_ctx)
751
{
Zachary T Welch's avatar
Zachary T Welch committed
752
	struct target *target;
753
	int retval;
oharboe's avatar
oharboe committed
754

755
	for (target = all_targets; target; target = target->next) {
756
		struct target_type *type = target->type;
757

758
		target_reset_examined(target);
759
760
761
762
		if (target->type->examine == NULL)
		{
			target->type->examine = default_examine;
		}
oharboe's avatar
oharboe committed
763

764
		if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
765
		{
zwelch's avatar
zwelch committed
766
			LOG_ERROR("target '%s' init failed", target_get_name(target));
767
			return retval;
768
		}
oharboe's avatar
oharboe committed
769

David Brownell's avatar
David Brownell committed
770
771
772
773
		/**
		 * @todo MCR/MRC are ARM-specific; don't require them in
		 * all targets, or for ARMs without coprocessors.
		 */
774
775
776
		if (target->type->mcr == NULL)
		{
			target->type->mcr = default_mcr;
777
778
779
780
781
782
783
784
		} else
		{
			/* FIX! multiple targets will generally register global commands
			 * multiple times. Only register this one if *one* of the
			 * targets need the command. Hmm... make it a command on the
			 * Jim Tcl target object?
			 */
			register_jim(cmd_ctx, "mcr", jim_mcrmrc, "write coprocessor <cpnum> <op1> <op2> <CRn> <CRm> <value>");
785
786
787
788
789
		}

		if (target->type->mrc == NULL)
		{
			target->type->mrc = default_mrc;
790
791
792
		} else
		{
			register_jim(cmd_ctx, "mrc", jim_mcrmrc, "read coprocessor <cpnum> <op1> <op2> <CRn> <CRm>");
793
794
795
		}


David Brownell's avatar
David Brownell committed
796
797
798
799
800
801
		/**
		 * @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.
		 */

802
803
804
805
806
807
808
809
810
811
812
813
		/* 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;

814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
		/* 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 %s",
						type->name,
						"write_phys_memory");
				type->write_phys_memory = err_write_phys_memory;
			}
			if (type->read_phys_memory == NULL) {
				LOG_ERROR("type '%s' is missing %s",
						type->name,
						"read_phys_memory");
				type->read_phys_memory = err_read_phys_memory;
			}
			if (type->virt2phys == NULL) {
				LOG_ERROR("type '%s' is missing %s",
						type->name,
						"virt2phys");
				type->virt2phys = identity_virt2phys;
			}

		/* 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.
		 */
		} else {
			if (type->write_phys_memory
					|| type->read_phys_memory
					|| type->virt2phys)
				LOG_WARNING("type '%s' has broken MMU hooks",
						type->name);

			type->mmu = no_mmu;
			type->write_phys_memory = type->write_memory;
			type->read_phys_memory = type->read_memory;
			type->virt2phys = identity_virt2phys;
852
853
		}
	}
oharboe's avatar
oharboe committed
854

855
	if (all_targets)
856
	{
zwelch's avatar
zwelch committed
857
		if ((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK)
858
			return retval;
zwelch's avatar
zwelch committed
859
		if ((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK)
860
			return retval;
861
	}
oharboe's avatar
oharboe committed
862

863
864
865
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
866
int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
867
{
868
	struct target_event_callback **callbacks_p = &target_event_callbacks;
oharboe's avatar
oharboe committed
869

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

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

882
	(*callbacks_p) = malloc(sizeof(struct target_event_callback));
883
884
885
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
886

887
888
889
890
891
	return ERROR_OK;
}

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

895
896
897
898
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
899

900
901
902
903
904
905
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
906

907
	(*callbacks_p) = malloc(sizeof(struct target_timer_callback));
908
909
910
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->periodic = periodic;
	(*callbacks_p)->time_ms = time_ms;
oharboe's avatar
oharboe committed
911

912
913
914
915
916
917
918
919
920
	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
921

922
923
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
924

925
926
927
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
928
int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
929
{
930
931
	struct target_event_callback **p = &target_event_callbacks;
	struct target_event_callback *c = target_event_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_event_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
955
956
	return ERROR_OK;
}

int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
{
957
958
	struct target_timer_callback **p = &target_timer_callbacks;
	struct target_timer_callback *c = target_timer_callbacks;
oharboe's avatar
oharboe committed
959

960
961
962
963
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
964

965
966
	while (c)
	{
967
		struct target_timer_callback *next = c->next;
968
969
970
971
972
973
974
975
976
977
		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
978

979
980
981
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
982
int target_call_event_callbacks(struct target *target, enum target_event event)
983
{
984
985
	struct target_event_callback *callback = target_event_callbacks;
	struct target_event_callback *next_callback;
oharboe's avatar
oharboe committed
986

987
988
989
	if (event == TARGET_EVENT_HALTED)
	{
		/* execute early halted first */
990
		target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
991
992
	}

993
994
	LOG_DEBUG("target event %i (%s)",
			  event,
995
			  Jim_Nvp_value2name_simple(nvp_target_event, event)->name);
oharboe's avatar
oharboe committed
996

997
	target_handle_event(target, event);
998

999
1000
	while (callback)
	{
For faster browsing, not all history is shown. View entire blame