target.c 128 KB
Newer Older
4001
4002
4003

		fn = target_write_phys_memory;
	}
4004

4005
	jim_wide a;
4006
	e = Jim_GetOpt_Wide(&goi, &a);
4007
4008
	if (e != JIM_OK)
		return e;
4009

4010
4011
4012
	jim_wide b;
	e = Jim_GetOpt_Wide(&goi, &b);
	if (e != JIM_OK)
4013
		return e;
4014
4015

	jim_wide c = 1;
4016
	if (goi.argc == 1)
4017
4018
4019
4020
	{
		e = Jim_GetOpt_Wide(&goi, &c);
		if (e != JIM_OK)
			return e;
4021
4022
	}

4023
4024
4025
4026
4027
4028
	/* all args must be consumed */
	if (goi.argc != 0)
	{
		return JIM_ERR;
	}

4029
	struct target *target = Jim_CmdPrivData(goi.interp);
Øyvind Harboe's avatar
Øyvind Harboe committed
4030
	unsigned data_size;
4031
	if (strcasecmp(cmd_name, "mww") == 0) {
Øyvind Harboe's avatar
Øyvind Harboe committed
4032
		data_size = 4;
4033
4034
	}
	else if (strcasecmp(cmd_name, "mwh") == 0) {
Øyvind Harboe's avatar
Øyvind Harboe committed
4035
		data_size = 2;
4036
4037
	}
	else if (strcasecmp(cmd_name, "mwb") == 0) {
Øyvind Harboe's avatar
Øyvind Harboe committed
4038
		data_size = 1;
4039
4040
4041
4042
	} else {
		LOG_ERROR("command '%s' unknown: ", cmd_name);
		return JIM_ERR;
	}
4043

4044
	return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR;
4045
}
4046

4047
4048
4049
static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	const char *cmd_name = Jim_GetString(argv[0], NULL);
4050

4051
4052
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
4053

4054
	if ((goi.argc < 1) || (goi.argc > 3))
4055
4056
	{
		Jim_SetResult_sprintf(goi.interp,
4057
				"usage: %s [phys] <address> [<count>]", cmd_name);
4058
4059
		return JIM_ERR;
	}
4060

4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
	int (*fn)(struct target *target,
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	fn=target_read_memory;

	int e;
	if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0)
	{
		/* consume it */
		struct Jim_Obj *obj;
		e = Jim_GetOpt_Obj(&goi, &obj);
		if (e != JIM_OK)
			return e;

		fn=target_read_phys_memory;
	}

4077
	jim_wide a;
4078
	e = Jim_GetOpt_Wide(&goi, &a);
4079
4080
4081
4082
	if (e != JIM_OK) {
		return JIM_ERR;
	}
	jim_wide c;
4083
	if (goi.argc == 1) {
4084
		e = Jim_GetOpt_Wide(&goi, &c);
zwelch's avatar
zwelch committed
4085
		if (e != JIM_OK) {
4086
4087
			return JIM_ERR;
		}
4088
4089
4090
	} else {
		c = 1;
	}
4091
4092
4093
4094
4095
4096
4097

	/* all args must be consumed */
	if (goi.argc != 0)
	{
		return JIM_ERR;
	}

4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
	jim_wide b = 1; /* shut up gcc */
	if (strcasecmp(cmd_name, "mdw") == 0)
		b = 4;
	else if (strcasecmp(cmd_name, "mdh") == 0)
		b = 2;
	else if (strcasecmp(cmd_name, "mdb") == 0)
		b = 1;
	else {
		LOG_ERROR("command '%s' unknown: ", cmd_name);
		return JIM_ERR;
	}

	/* convert count to "bytes" */
	c = c * b;

	struct target *target = Jim_CmdPrivData(goi.interp);
	uint8_t  target_buf[32];
	jim_wide x, y, z;
	while (c > 0) {
		y = c;
		if (y > 16) {
			y = 16;
4120
		}
4121
		e = fn(target, a, b, y / b, target_buf);
4122
4123
4124
		if (e != ERROR_OK) {
			Jim_SetResult_sprintf(interp, "error reading target @ 0x%08lx", (int)(a));
			return JIM_ERR;
4125
4126
		}

4127
4128
4129
4130
4131
		Jim_fprintf(interp, interp->cookie_stdout, "0x%08x ", (int)(a));
		switch (b) {
		case 4:
			for (x = 0; x < 16 && x < y; x += 4)
			{
4132
				z = target_buffer_get_u32(target, &(target_buf[ x ]));
4133
				Jim_fprintf(interp, interp->cookie_stdout, "%08x ", (int)(z));
4134
			}
4135
4136
			for (; (x < 16) ; x += 4) {
				Jim_fprintf(interp, interp->cookie_stdout, "         ");
4137
			}
4138
4139
4140
4141
			break;
		case 2:
			for (x = 0; x < 16 && x < y; x += 2)
			{
4142
				z = target_buffer_get_u16(target, &(target_buf[ x ]));
4143
				Jim_fprintf(interp, interp->cookie_stdout, "%04x ", (int)(z));
4144
			}
4145
4146
			for (; (x < 16) ; x += 2) {
				Jim_fprintf(interp, interp->cookie_stdout, "     ");
4147
			}
4148
4149
4150
4151
			break;
		case 1:
		default:
			for (x = 0 ; (x < 16) && (x < y) ; x += 1) {
4152
				z = target_buffer_get_u8(target, &(target_buf[ x ]));
4153
				Jim_fprintf(interp, interp->cookie_stdout, "%02x ", (int)(z));
4154
			}
4155
4156
			for (; (x < 16) ; x += 1) {
				Jim_fprintf(interp, interp->cookie_stdout, "   ");
4157
			}
4158
			break;
4159
		}
4160
4161
4162
4163
4164
4165
4166
4167
4168
		/* ascii-ify the bytes */
		for (x = 0 ; x < y ; x++) {
			if ((target_buf[x] >= 0x20) &&
				(target_buf[x] <= 0x7e)) {
				/* good */
			} else {
				/* smack it */
				target_buf[x] = '.';
			}
4169
		}
4170
4171
4172
4173
		/* space pad  */
		while (x < 16) {
			target_buf[x] = ' ';
			x++;
4174
		}
4175
4176
4177
4178
4179
4180
4181
		/* terminate */
		target_buf[16] = 0;
		/* print - with a newline */
		Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf);
		/* NEXT... */
		c -= 16;
		a += 16;
4182
	}
4183
4184
4185
	return JIM_OK;
}

4186
4187
static int jim_target_mem2array(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv)
4188
4189
4190
4191
4192
{
	struct target *target = Jim_CmdPrivData(interp);
	return target_mem2array(interp, target, argc - 1, argv + 1);
}

4193
4194
static int jim_target_array2mem(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv)
4195
4196
4197
4198
{
	struct target *target = Jim_CmdPrivData(interp);
	return target_array2mem(interp, target, argc - 1, argv + 1);
}
zwelch's avatar
zwelch committed
4199

4200
4201
static int jim_target_tap_disabled(Jim_Interp *interp)
{
zwelch's avatar
zwelch committed
4202
4203
	Jim_SetResult_sprintf(interp, "[TAP is disabled]");
	return JIM_ERR;
4204
4205
}

4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
		return JIM_ERR;
	}
	struct target *target = Jim_CmdPrivData(interp);
	if (!target->tap->enabled)
		return jim_target_tap_disabled(interp);

	int e = target->type->examine(target);
	if (e != ERROR_OK)
	{
		Jim_SetResult_sprintf(interp, "examine-fails: %d", e);
		return JIM_ERR;
	}
	return JIM_OK;
}

4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
		return JIM_ERR;
	}
	struct target *target = Jim_CmdPrivData(interp);

	if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK)
		return JIM_ERR;

	return JIM_OK;
}

4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
		return JIM_ERR;
	}
	struct target *target = Jim_CmdPrivData(interp);
	if (!target->tap->enabled)
		return jim_target_tap_disabled(interp);

	int e;
	if (!(target_was_examined(target))) {
		e = ERROR_TARGET_NOT_EXAMINED;
	} else {
		e = target->type->poll(target);
	}
	if (e != ERROR_OK)
	{
		Jim_SetResult_sprintf(interp, "poll-fails: %d", e);
		return JIM_ERR;
	}
	return JIM_OK;
}

static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);

	if (goi.argc != 2)
	{
		Jim_WrongNumArgs(interp, 0, argv,
				"([tT]|[fF]|assert|deassert) BOOL");
		return JIM_ERR;
	}

	Jim_Nvp *n;
	int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n);
	if (e != JIM_OK)
	{
		Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1);
		return e;
	}
	/* the halt or not param */
	jim_wide a;
	e = Jim_GetOpt_Wide(&goi, &a);
	if (e != JIM_OK)
		return e;

	struct target *target = Jim_CmdPrivData(goi.interp);
	if (!target->tap->enabled)
		return jim_target_tap_disabled(interp);
Antonio Borneo's avatar
Antonio Borneo committed
4294
4295
4296
4297
4298
	if (!(target_was_examined(target)))
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_TARGET_NOT_EXAMINED;
	}
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
	if (!target->type->assert_reset || !target->type->deassert_reset)
	{
		Jim_SetResult_sprintf(interp,
				"No target-specific reset for %s",
				target_name(target));
		return JIM_ERR;
	}
	/* determine if we should halt or not. */
	target->reset_halt = !!a;
	/* When this happens - all workareas are invalid. */
	target_free_all_working_areas_restore(target, 0);

	/* do the assert */
	if (n->value == NVP_ASSERT) {
		e = target->type->assert_reset(target);
	} else {
		e = target->type->deassert_reset(target);
	}
	return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
}

static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1) {
		Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
		return JIM_ERR;
	}
	struct target *target = Jim_CmdPrivData(interp);
	if (!target->tap->enabled)
		return jim_target_tap_disabled(interp);
	int e = target->type->halt(target);
	return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
}

static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);

	/* params:  <name>  statename timeoutmsecs */
	if (goi.argc != 2)
	{
		const char *cmd_name = Jim_GetString(argv[0], NULL);
		Jim_SetResult_sprintf(goi.interp,
				"%s <state_name> <timeout_in_msec>", cmd_name);
		return JIM_ERR;
	}

	Jim_Nvp *n;
	int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n);
	if (e != JIM_OK) {
		Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1);
		return e;
	}
	jim_wide a;
	e = Jim_GetOpt_Wide(&goi, &a);
	if (e != JIM_OK) {
		return e;
	}
	struct target *target = Jim_CmdPrivData(interp);
	if (!target->tap->enabled)
		return jim_target_tap_disabled(interp);

	e = target_wait_state(target, n->value, a);
	if (e != ERROR_OK)
	{
		Jim_SetResult_sprintf(goi.interp,
				"target: %s wait %s fails (%d) %s",
				target_name(target), n->name,
				e, target_strerror_safe(e));
		return JIM_ERR;
	}
	return JIM_OK;
}
/* List for human, Events defined for this target.
 * scripts/programs should use 'name cget -event NAME'
 */
static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
4378
4379
4380
	struct command_context *cmd_ctx = current_command_context(interp);
	assert (cmd_ctx != NULL);

4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
	struct target *target = Jim_CmdPrivData(interp);
	struct target_event_action *teap = target->event_action;
	command_print(cmd_ctx, "Event actions for target (%d) %s\n",
				   target->target_number,
				   target_name(target));
	command_print(cmd_ctx, "%-25s | Body", "Event");
	command_print(cmd_ctx, "------------------------- | "
			"----------------------------------------");
	while (teap)
	{
		Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event);
		command_print(cmd_ctx, "%-25s | %s",
				opt->name, Jim_GetString(teap->body, NULL));
		teap = teap->next;
	}
	command_print(cmd_ctx, "***END***");
	return JIM_OK;
}
static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
		return JIM_ERR;
	}
	struct target *target = Jim_CmdPrivData(interp);
	Jim_SetResultString(interp, target_state_name(target), -1);
	return JIM_OK;
}
static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
	if (goi.argc != 1)
	{
		const char *cmd_name = Jim_GetString(argv[0], NULL);
		Jim_SetResult_sprintf(goi.interp, "%s <eventname>", cmd_name);
		return JIM_ERR;
	}
	Jim_Nvp *n;
	int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n);
	if (e != JIM_OK)
	{
		Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
		return e;
	}
	struct target *target = Jim_CmdPrivData(interp);
	target_handle_event(target, n->value);
	return JIM_OK;
}

static const struct command_registration target_instance_command_handlers[] = {
	{
		.name = "configure",
		.mode = COMMAND_CONFIG,
4436
		.jim_handler = jim_target_configure,
4437
		.help  = "configure a new target for use",
4438
		.usage = "[target_attribute ...]",
4439
4440
4441
4442
	},
	{
		.name = "cget",
		.mode = COMMAND_ANY,
4443
4444
4445
		.jim_handler = jim_target_configure,
		.help  = "returns the specified target attribute",
		.usage = "target_attribute",
4446
4447
4448
4449
	},
	{
		.name = "mww",
		.mode = COMMAND_EXEC,
4450
		.jim_handler = jim_target_mw,
4451
		.help = "Write 32-bit word(s) to target memory",
4452
		.usage = "address data [count]",
4453
4454
4455
4456
	},
	{
		.name = "mwh",
		.mode = COMMAND_EXEC,
4457
		.jim_handler = jim_target_mw,
4458
		.help = "Write 16-bit half-word(s) to target memory",
4459
		.usage = "address data [count]",
4460
4461
4462
4463
	},
	{
		.name = "mwb",
		.mode = COMMAND_EXEC,
4464
		.jim_handler = jim_target_mw,
4465
		.help = "Write byte(s) to target memory",
4466
		.usage = "address data [count]",
4467
4468
4469
4470
	},
	{
		.name = "mdw",
		.mode = COMMAND_EXEC,
4471
		.jim_handler = jim_target_md,
4472
		.help = "Display target memory as 32-bit words",
4473
		.usage = "address [count]",
4474
4475
4476
4477
	},
	{
		.name = "mdh",
		.mode = COMMAND_EXEC,
4478
		.jim_handler = jim_target_md,
4479
		.help = "Display target memory as 16-bit half-words",
4480
		.usage = "address [count]",
4481
4482
4483
4484
	},
	{
		.name = "mdb",
		.mode = COMMAND_EXEC,
4485
		.jim_handler = jim_target_md,
4486
		.help = "Display target memory as 8-bit bytes",
4487
		.usage = "address [count]",
4488
4489
4490
4491
	},
	{
		.name = "array2mem",
		.mode = COMMAND_EXEC,
4492
4493
4494
4495
		.jim_handler = jim_target_array2mem,
		.help = "Writes Tcl array of 8/16/32 bit numbers "
			"to target memory",
		.usage = "arrayname bitwidth address count",
4496
4497
4498
4499
	},
	{
		.name = "mem2array",
		.mode = COMMAND_EXEC,
4500
4501
4502
4503
		.jim_handler = jim_target_mem2array,
		.help = "Loads Tcl array of 8/16/32 bit numbers "
			"from target memory",
		.usage = "arrayname bitwidth address count",
4504
4505
4506
4507
	},
	{
		.name = "eventlist",
		.mode = COMMAND_EXEC,
4508
4509
		.jim_handler = jim_target_event_list,
		.help = "displays a table of events defined for this target",
4510
4511
4512
4513
	},
	{
		.name = "curstate",
		.mode = COMMAND_EXEC,
4514
4515
		.jim_handler = jim_target_current_state,
		.help = "displays the current state of this target",
4516
4517
4518
4519
	},
	{
		.name = "arp_examine",
		.mode = COMMAND_EXEC,
4520
4521
		.jim_handler = jim_target_examine,
		.help = "used internally for reset processing",
4522
	},
4523
4524
4525
4526
4527
4528
	{
		.name = "arp_halt_gdb",
		.mode = COMMAND_EXEC,
		.jim_handler = jim_target_halt_gdb,
		.help = "used internally for reset processing to halt GDB",
	},
4529
4530
4531
	{
		.name = "arp_poll",
		.mode = COMMAND_EXEC,
4532
4533
		.jim_handler = jim_target_poll,
		.help = "used internally for reset processing",
4534
4535
4536
4537
	},
	{
		.name = "arp_reset",
		.mode = COMMAND_EXEC,
4538
4539
		.jim_handler = jim_target_reset,
		.help = "used internally for reset processing",
4540
4541
4542
4543
	},
	{
		.name = "arp_halt",
		.mode = COMMAND_EXEC,
4544
4545
		.jim_handler = jim_target_halt,
		.help = "used internally for reset processing",
4546
4547
4548
4549
	},
	{
		.name = "arp_waitstate",
		.mode = COMMAND_EXEC,
4550
4551
		.jim_handler = jim_target_wait_state,
		.help = "used internally for reset processing",
4552
4553
4554
4555
	},
	{
		.name = "invoke-event",
		.mode = COMMAND_EXEC,
4556
4557
4558
		.jim_handler = jim_target_invoke_event,
		.help = "invoke handler for specified event",
		.usage = "event_name",
4559
4560
4561
4562
	},
	COMMAND_REGISTRATION_DONE
};

4563
static int target_create(Jim_GetOptInfo *goi)
4564
{
4565
4566
4567
4568
4569
4570
	Jim_Obj *new_cmd;
	Jim_Cmd *cmd;
	const char *cp;
	char *cp2;
	int e;
	int x;
Zachary T Welch's avatar
Zachary T Welch committed
4571
	struct target *target;
4572
	struct command_context *cmd_ctx;
4573

4574
4575
4576
	cmd_ctx = current_command_context(goi->interp);
	assert (cmd_ctx != NULL);

zwelch's avatar
zwelch committed
4577
	if (goi->argc < 3) {
4578
		Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
4579
4580
4581
4582
		return JIM_ERR;
	}

	/* COMMAND */
4583
	Jim_GetOpt_Obj(goi, &new_cmd);
4584
	/* does this command exist? */
4585
	cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
zwelch's avatar
zwelch committed
4586
	if (cmd) {
4587
		cp = Jim_GetString(new_cmd, NULL);
4588
4589
4590
		Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
		return JIM_ERR;
	}
4591

4592
	/* TYPE */
4593
	e = Jim_GetOpt_String(goi, &cp2, NULL);
4594
4595
	cp = cp2;
	/* now does target type exist */
zwelch's avatar
zwelch committed
4596
4597
	for (x = 0 ; target_types[x] ; x++) {
		if (0 == strcmp(cp, target_types[x]->name)) {
4598
4599
4600
4601
			/* found */
			break;
		}
	}
zwelch's avatar
zwelch committed
4602
	if (target_types[x] == NULL) {
4603
		Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp);
zwelch's avatar
zwelch committed
4604
4605
		for (x = 0 ; target_types[x] ; x++) {
			if (target_types[x + 1]) {
4606
				Jim_AppendStrings(goi->interp,
4607
4608
4609
4610
								   Jim_GetResult(goi->interp),
								   target_types[x]->name,
								   ", ", NULL);
			} else {
4611
				Jim_AppendStrings(goi->interp,
4612
4613
								   Jim_GetResult(goi->interp),
								   " or ",
4614
								   target_types[x]->name,NULL);
4615
4616
4617
4618
4619
4620
			}
		}
		return JIM_ERR;
	}

	/* Create it */
Zachary T Welch's avatar
Zachary T Welch committed
4621
	target = calloc(1,sizeof(struct target));
4622
4623
4624
4625
	/* set target number */
	target->target_number = new_target_number();

	/* allocate memory for each unique target type */
4626
	target->type = (struct target_type*)calloc(1,sizeof(struct target_type));
4627

4628
	memcpy(target->type, target_types[x], sizeof(struct target_type));
4629

4630
4631
4632
4633
4634
4635
4636
	/* will be set by "-endian" */
	target->endianness = TARGET_ENDIAN_UNKNOWN;

	target->working_area        = 0x0;
	target->working_area_size   = 0x0;
	target->working_areas       = NULL;
	target->backup_working_area = 0;
4637

4638
4639
4640
4641
4642
4643
4644
	target->state               = TARGET_UNKNOWN;
	target->debug_reason        = DBG_REASON_UNDEFINED;
	target->reg_cache           = NULL;
	target->breakpoints         = NULL;
	target->watchpoints         = NULL;
	target->next                = NULL;
	target->arch_info           = NULL;
4645

4646
4647
	target->display             = 1;

4648
4649
	target->halt_issued			= false;

4650
	/* initialize trace information */
Zachary T Welch's avatar
Zachary T Welch committed
4651
	target->trace_info = malloc(sizeof(struct trace));
4652
4653
4654
4655
4656
4657
4658
	target->trace_info->num_trace_points         = 0;
	target->trace_info->trace_points_size        = 0;
	target->trace_info->trace_points             = NULL;
	target->trace_info->trace_history_size       = 0;
	target->trace_info->trace_history            = NULL;
	target->trace_info->trace_history_pos        = 0;
	target->trace_info->trace_history_overflowed = 0;
4659

4660
4661
4662
4663
4664
4665
4666
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

	/* Do the rest as "configure" options */
	goi->isconfigure = 1;
4667
	e = target_configure(goi, target);
4668
4669
4670

	if (target->tap == NULL)
	{
4671
		Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
zwelch's avatar
zwelch committed
4672
		e = JIM_ERR;
4673
4674
	}

zwelch's avatar
zwelch committed
4675
	if (e != JIM_OK) {
4676
4677
		free(target->type);
		free(target);
4678
4679
4680
		return e;
	}

zwelch's avatar
zwelch committed
4681
	if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
4682
4683
4684
4685
		/* default endian to little if not specified */
		target->endianness = TARGET_LITTLE_ENDIAN;
	}

4686
4687
4688
	/* incase variant is not set */
	if (!target->variant)
		target->variant = strdup("");
4689

4690
4691
4692
	cp = Jim_GetString(new_cmd, NULL);
	target->cmd_name = strdup(cp);

4693
	/* create the target specific commands */
4694
4695
4696
4697
	if (target->type->commands) {
		e = register_commands(cmd_ctx, NULL, target->type->commands);
		if (ERROR_OK != e)
			LOG_ERROR("unable to register '%s' commands", cp);
4698
	}
zwelch's avatar
zwelch committed
4699
	if (target->type->target_create) {
4700
		(*(target->type->target_create))(target, goi->interp);
4701
4702
4703
4704
	}

	/* append to end of list */
	{
Zachary T Welch's avatar
Zachary T Welch committed
4705
		struct target **tpp;
4706
		tpp = &(all_targets);
zwelch's avatar
zwelch committed
4707
		while (*tpp) {
4708
			tpp = &((*tpp)->next);
4709
4710
4711
		}
		*tpp = target;
	}
4712

4713
	/* now - create the new target name command */
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
	const const struct command_registration target_subcommands[] = {
		{
			.chain = target_instance_command_handlers,
		},
		{
			.chain = target->type->commands,
		},
		COMMAND_REGISTRATION_DONE
	};
	const const struct command_registration target_commands[] = {
		{
			.name = cp,
			.mode = COMMAND_ANY,
			.help = "target command group",
			.chain = target_subcommands,
		},
		COMMAND_REGISTRATION_DONE
4731
	};
4732
4733
4734
4735
4736
4737
4738
4739
4740
	e = register_commands(cmd_ctx, NULL, target_commands);
	if (ERROR_OK != e)
		return JIM_ERR;

	struct command *c = command_find_in_context(cmd_ctx, cp);
	assert(c);
	command_set_handler_data(c, target);

	return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
4741
4742
}

4743
static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4744
{
4745
4746
4747
4748
4749
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
		return JIM_ERR;
	}
4750
4751
4752
	struct command_context *cmd_ctx = current_command_context(interp);
	assert (cmd_ctx != NULL);

4753
4754
4755
	Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1);
	return JIM_OK;
}
4756

4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
		return JIM_ERR;
	}
	Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
	for (unsigned x = 0; NULL != target_types[x]; x++)
	{
		Jim_ListAppendElement(interp, Jim_GetResult(interp),
			Jim_NewStringObj(interp, target_types[x]->name, -1));
	}
	return JIM_OK;
}
4772

4773
4774
4775
4776
4777
static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
4778
4779
		return JIM_ERR;
	}
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
	Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
	struct target *target = all_targets;
	while (target)
	{
		Jim_ListAppendElement(interp, Jim_GetResult(interp),
			Jim_NewStringObj(interp, target_name(target), -1));
		target = target->next;
	}
	return JIM_OK;
}
4790

4791
4792
4793
4794
4795
4796
4797
4798
4799
static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
	if (goi.argc < 3)
	{
		Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
			"<name> <target_type> [<target_options> ...]");
		return JIM_ERR;
4800
	}
4801
4802
	return target_create(&goi);
}
4803

4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
static int jim_target_number(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);

	/* It's OK to remove this mechanism sometime after August 2010 or so */
	LOG_WARNING("don't use numbers as target identifiers; use names");
	if (goi.argc != 1)
	{
		Jim_SetResult_sprintf(goi.interp, "usage: target number <number>");
4814
		return JIM_ERR;
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
	}
	jim_wide w;
	int e = Jim_GetOpt_Wide(&goi, &w);
	if (e != JIM_OK)
		return JIM_ERR;

	struct target *target;
	for (target = all_targets; NULL != target; target = target->next)
	{
		if (target->target_number != w)
4825
			continue;
4826
4827

		Jim_SetResultString(goi.interp, target_name(target), -1);
4828
4829
		return JIM_OK;
	}
4830
4831
	Jim_SetResult_sprintf(goi.interp,
			"Target: number %d does not exist", (int)(w));
4832
	return JIM_ERR;
4833
}
4834

4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
static int jim_target_count(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "<no parameters>");
		return JIM_ERR;
	}
	unsigned count = 0;
	struct target *target = all_targets;
	while (NULL != target)
	{
		target = target->next;
		count++;
	}
	Jim_SetResult(interp, Jim_NewIntObj(interp, count));
	return JIM_OK;
}

static const struct command_registration target_subcommand_handlers[] = {
4854
4855
4856
	{
		.name = "init",
		.mode = COMMAND_CONFIG,
4857
		.handler = handle_target_init_command,
4858
4859
		.help = "initialize targets",
	},
4860
4861
	{
		.name = "create",
4862
		/* REVISIT this should be COMMAND_CONFIG ... */
4863
		.mode = COMMAND_ANY,
4864
4865
4866
		.jim_handler = jim_target_create,
		.usage = "name type '-chain-position' name [options ...]",
		.help = "Creates and selects a new target",
4867
4868
4869
4870
	},
	{
		.name = "current",
		.mode = COMMAND_ANY,
4871
		.jim_handler = jim_target_current,
4872
4873
4874
4875
4876
		.help = "Returns the currently selected target",
	},
	{
		.name = "types",
		.mode = COMMAND_ANY,
4877
4878
4879
		.jim_handler = jim_target_types,
		.help = "Returns the available target types as "
				"a list of strings",
4880
4881
4882
4883
	},
	{
		.name = "names",
		.mode = COMMAND_ANY,
4884
		.jim_handler = jim_target_names,
4885
4886
4887
4888
4889
		.help = "Returns the names of all targets as a list of strings",
	},
	{
		.name = "number",
		.mode = COMMAND_ANY,
4890
4891
4892
4893
		.jim_handler = jim_target_number,
		.usage = "number",
		.help = "Returns the name of the numbered target "
			"(DEPRECATED)",
4894
4895
4896
4897
	},
	{
		.name = "count",
		.mode = COMMAND_ANY,
4898
4899
4900
		.jim_handler = jim_target_count,
		.help = "Returns the number of targets as an integer "
			"(DEPRECATED)",
4901
4902
4903
4904
	},
	COMMAND_REGISTRATION_DONE
};

4905
4906
struct FastLoad
{
4907
	uint32_t address;
4908
	uint8_t *data;
4909
4910
4911
4912
4913
4914
4915
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

4916
static void free_fastload(void)
4917
{
zwelch's avatar
zwelch committed
4918
	if (fastload != NULL)
4919
4920
	{
		int i;
zwelch's avatar
zwelch committed
4921
		for (i = 0; i < fastload_num; i++)
4922
4923
4924
4925
4926
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
zwelch's avatar
zwelch committed
4927
		fastload = NULL;
4928
4929
4930
4931
4932
4933
	}
}




4934
COMMAND_HANDLER(handle_fast_load_image_command)
4935
{
4936
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
4937
	size_t buf_cnt;
4938
	uint32_t image_size;
zwelch's avatar
zwelch committed
4939
4940
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
4941
4942
	int i;

Zachary T Welch's avatar
Zachary T Welch committed
4943
	struct image image;
4944

4945
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
4946
4947
4948
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;
4949

Zachary T Welch's avatar
Zachary T Welch committed
4950
4951
	struct duration bench;
	duration_start(&bench);
4952

4953
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
4954
4955
4956
4957
4958
4959
	{
		return ERROR_OK;
	}

	image_size = 0x0;
	retval = ERROR_OK;
zwelch's avatar
zwelch committed
4960
4961
	fastload_num = image.num_sections;
	fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
zwelch's avatar
zwelch committed
4962
	if (fastload == NULL)
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
	{
		image_close(&image);
		return ERROR_FAIL;
	}
	memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
4973
			command_print(CMD_CTX, "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
4974
						  (int)(image.sections[i].size));
4975
4976
4977
4978
4979
4980
4981
4982
4983
			break;
		}

		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
			break;
		}

zwelch's avatar
zwelch committed
4984
4985
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
4986
4987
4988
4989


		/* DANGER!!! beware of unsigned comparision here!!! */

zwelch's avatar
zwelch committed
4990
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
4991
				(image.sections[i].base_address < max_address))
4992
		{
zwelch's avatar
zwelch committed
4993
			if (image.sections[i].base_address < min_address)
4994
4995
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
4996
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
4997
				length -= offset;
4998
4999
			}

zwelch's avatar
zwelch committed
5000
			if (image.sections[i].base_address + buf_cnt > max_address)
For faster browsing, not all history is shown. View entire blame