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

48
49
50
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);

51
/* targets */
52
53
54
55
56
57
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;
58
extern target_type_t fa526_target;
59
extern target_type_t feroceon_target;
60
extern target_type_t dragonite_target;
61
62
extern target_type_t xscale_target;
extern target_type_t cortexm3_target;
63
extern target_type_t cortexa8_target;
oharboe's avatar
oharboe committed
64
extern target_type_t arm11_target;
ntfreak's avatar
ntfreak committed
65
extern target_type_t mips_m4k_target;
66
extern target_type_t avr_target;
67
68
69
70
71
72
73
74
75

target_type_t *target_types[] =
{
	&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,
};

88
target_t *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
216
217
218
219
220
221
222
223
224
225
226
const char *
target_state_name( target_t *t )
{
	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
230
231
232
233
234
235
{
	target_t *t;
	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
246
/* read a uint32_t from a buffer in target memory endianness */
uint32_t target_buffer_get_u32(target_t *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
255
/* read a uint16_t from a buffer in target memory endianness */
uint16_t target_buffer_get_u16(target_t *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
264
/* read a uint8_t from a buffer in target memory endianness */
uint8_t target_buffer_get_u8(target_t *target, const uint8_t *buffer)
265
266
267
268
{
	return *buffer & 0x0ff;
}

269
270
/* write a uint32_t to a buffer in target memory endianness */
void target_buffer_set_u32(target_t *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
279
/* write a uint16_t to a buffer in target memory endianness */
void target_buffer_set_u16(target_t *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
288
/* write a uint8_t to a buffer in target memory endianness */
void target_buffer_set_u8(target_t *target, uint8_t *buffer, uint8_t value)
289
290
291
292
{
	*buffer = value;
}

293
294
295
296
297
298
299
300
301
302
303
304
305
/* 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;
	}

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 */
325
static target_t *get_target_by_num(int num)
326
{
327
	target_t *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
339
340
341
		target = target->next;
	}

	return NULL;
}

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
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
}

352
353
int target_poll(struct target_s *target)
{
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
387
388
}

int target_halt(struct target_s *target)
{
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
}

407
int target_resume(struct target_s *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
}

oharboe's avatar
oharboe committed
428
int target_process_reset(struct command_context_s *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
}

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

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

476
static int default_examine(struct target_s *target)
477
{
478
	target_set_examined(target);
479
480
481
	return ERROR_OK;
}

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

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

	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;
zwelch's avatar
zwelch committed
507
508
509
	target_t *target;

	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;
}
zwelch's avatar
zwelch committed
522
523
524
525
const char *target_get_name(struct target_s *target)
{
	return target->type->name;
}
526

527
static int target_write_memory_imp(struct target_s *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);
}

537
static int target_read_memory_imp(struct target_s *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
547
548
	{
		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)
{
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);
}

562
static int target_run_algorithm_imp(struct target_s *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

zwelch's avatar
zwelch committed
572
int target_read_memory(struct target_s *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);
}

578
579
580
581
582
583
int target_read_phys_memory(struct target_s *target,
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target->type->read_phys_memory(target, address, size, count, buffer);
}

zwelch's avatar
zwelch committed
584
int target_write_memory(struct target_s *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
590
591
592
593
594
595

int target_write_phys_memory(struct target_s *target,
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target->type->write_phys_memory(target, address, size, count, buffer);
}

zwelch's avatar
zwelch committed
596
int target_bulk_write_memory(struct target_s *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);
}

602
603
604
605
606
607
608
609
610
611
612
613
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,
614
		struct watchpoint *watchpoint)
615
616
617
618
{
	return target->type->add_watchpoint(target, watchpoint);
}
int target_remove_watchpoint(struct target_s *target,
619
		struct watchpoint *watchpoint)
620
621
622
{
	return target->type->remove_watchpoint(target, watchpoint);
}
zwelch's avatar
zwelch committed
623

zwelch's avatar
zwelch committed
624
625
626
627
628
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
629
int target_step(struct target_s *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

zwelch's avatar
zwelch committed
636
int target_run_algorithm(struct target_s *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
652
653
654
655
656
657
658
659
660
661
662
/// @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
663

664
665
666

static int default_mrc(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
{
667
	LOG_ERROR("Not implemented: %s", __func__);
668
669
670
671
672
	return ERROR_FAIL;
}

static int default_mcr(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
{
673
	LOG_ERROR("Not implemented: %s", __func__);
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
	return ERROR_FAIL;
}

static int arm_cp_check(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm)
{
	/* 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;
	}

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

698
	if (op2 > 7)
699
700
701
702
703
	{
		LOG_ERROR("Illegal op2");
		return ERROR_FAIL;
	}

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

710
	if (CRm > 15)
711
712
713
714
715
	{
		LOG_ERROR("Illegal CRm");
		return ERROR_FAIL;
	}

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
	return ERROR_OK;
}

int target_mrc(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
{
	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);
}

int target_mcr(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
{
	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);
}

741
static int
David Brownell's avatar
David Brownell committed
742
err_read_phys_memory(struct target_s *target, uint32_t address,
743
		uint32_t size, uint32_t count, uint8_t *buffer)
744
{
745
	LOG_ERROR("Not implemented: %s", __func__);
746
	return ERROR_FAIL;
747
748
}

749
static int
David Brownell's avatar
David Brownell committed
750
err_write_phys_memory(struct target_s *target, uint32_t address,
751
		uint32_t size, uint32_t count, uint8_t *buffer)
752
{
753
	LOG_ERROR("Not implemented: %s", __func__);
754
	return ERROR_FAIL;
755
756
}

757
758
int target_init(struct command_context_s *cmd_ctx)
{
759
	struct target_s *target;
760
	int retval;
oharboe's avatar
oharboe committed
761

762
763
764
	for (target = all_targets; target; target = target->next) {
		struct target_type_s *type = target->type;

765
		target_reset_examined(target);
766
767
768
769
		if (target->type->examine == NULL)
		{
			target->type->examine = default_examine;
		}
oharboe's avatar
oharboe committed
770

771
		if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
772
		{
zwelch's avatar
zwelch committed
773
			LOG_ERROR("target '%s' init failed", target_get_name(target));
774
			return retval;
775
		}
oharboe's avatar
oharboe committed
776

David Brownell's avatar
David Brownell committed
777
778
779
780
		/**
		 * @todo MCR/MRC are ARM-specific; don't require them in
		 * all targets, or for ARMs without coprocessors.
		 */
781
782
783
		if (target->type->mcr == NULL)
		{
			target->type->mcr = default_mcr;
784
785
786
787
788
789
790
791
		} 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>");
792
793
794
795
796
		}

		if (target->type->mrc == NULL)
		{
			target->type->mrc = default_mrc;
797
798
799
		} else
		{
			register_jim(cmd_ctx, "mrc", jim_mcrmrc, "read coprocessor <cpnum> <op1> <op2> <CRn> <CRm>");
800
801
802
		}


David Brownell's avatar
David Brownell committed
803
804
805
806
807
808
		/**
		 * @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.
		 */

809
810
811
812
813
814
815
816
817
818
819
820
		/* 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;

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
852
853
854
855
856
857
858
		/* 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;
859
860
		}
	}
oharboe's avatar
oharboe committed
861

862
	if (all_targets)
863
	{
zwelch's avatar
zwelch committed
864
		if ((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK)
865
			return retval;
zwelch's avatar
zwelch committed
866
		if ((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK)
867
			return retval;
868
	}
oharboe's avatar
oharboe committed
869

870
871
872
873
874
	return ERROR_OK;
}

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

877
878
879
880
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
881

882
883
884
885
886
887
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
888

889
	(*callbacks_p) = malloc(sizeof(struct target_event_callback));
890
891
892
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
893

894
895
896
897
898
	return ERROR_OK;
}

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

902
903
904
905
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
906

907
908
909
910
911
912
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
913

914
	(*callbacks_p) = malloc(sizeof(struct target_timer_callback));
915
916
917
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->periodic = periodic;
	(*callbacks_p)->time_ms = time_ms;
oharboe's avatar
oharboe committed
918

919
920
921
922
923
924
925
926
927
	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
928

929
930
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
931

932
933
934
935
936
	return ERROR_OK;
}

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

940
941
942
943
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
944

945
946
	while (c)
	{
947
		struct target_event_callback *next = c->next;
948
949
950
951
952
953
954
955
956
957
		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
958

959
960
961
962
963
	return ERROR_OK;
}

int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
{
964
965
	struct target_timer_callback **p = &target_timer_callbacks;
	struct target_timer_callback *c = target_timer_callbacks;
oharboe's avatar
oharboe committed
966

967
968
969
970
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
971

972
973
	while (c)
	{
974
		struct target_timer_callback *next = c->next;
975
976
977
978
979
980
981
982
983
984
		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
985

986
987
988
989
990
	return ERROR_OK;
}

int target_call_event_callbacks(target_t *target, enum target_event event)
{
991
992
	struct target_event_callback *callback = target_event_callbacks;
	struct target_event_callback *next_callback;
oharboe's avatar
oharboe committed
993

994
995
996
	if (event == TARGET_EVENT_HALTED)
	{
		/* execute early halted first */
997
		target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
998
999
	}

1000
	LOG_DEBUG("target event %i (%s)",