target.c 124 KB
Newer Older
4001
4002
4003
4004
		/* space pad  */
		while (x < 16) {
			target_buf[x] = ' ';
			x++;
4005
		}
4006
4007
4008
4009
4010
4011
4012
		/* terminate */
		target_buf[16] = 0;
		/* print - with a newline */
		Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf);
		/* NEXT... */
		c -= 16;
		a += 16;
4013
	}
4014
4015
4016
	return JIM_OK;
}

4017
4018
static int jim_target_mem2array(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv)
4019
4020
4021
4022
4023
{
	struct target *target = Jim_CmdPrivData(interp);
	return target_mem2array(interp, target, argc - 1, argv + 1);
}

4024
4025
static int jim_target_array2mem(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv)
4026
4027
4028
4029
{
	struct target *target = Jim_CmdPrivData(interp);
	return target_array2mem(interp, target, argc - 1, argv + 1);
}
zwelch's avatar
zwelch committed
4030

4031
4032
static int jim_target_tap_disabled(Jim_Interp *interp)
{
zwelch's avatar
zwelch committed
4033
4034
	Jim_SetResult_sprintf(interp, "[TAP is disabled]");
	return JIM_ERR;
4035
4036
}

4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
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;
}

4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
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;
}

4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
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
4125
4126
4127
4128
4129
	if (!(target_was_examined(target)))
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_TARGET_NOT_EXAMINED;
	}
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
	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)
{
	struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
	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,
4265
		.jim_handler = jim_target_configure,
4266
		.help  = "configure a new target for use",
4267
		.usage = "[target_attribute ...]",
4268
4269
4270
4271
	},
	{
		.name = "cget",
		.mode = COMMAND_ANY,
4272
4273
4274
		.jim_handler = jim_target_configure,
		.help  = "returns the specified target attribute",
		.usage = "target_attribute",
4275
4276
4277
4278
	},
	{
		.name = "mww",
		.mode = COMMAND_EXEC,
4279
		.jim_handler = jim_target_mw,
4280
		.help = "Write 32-bit word(s) to target memory",
4281
		.usage = "address data [count]",
4282
4283
4284
4285
	},
	{
		.name = "mwh",
		.mode = COMMAND_EXEC,
4286
		.jim_handler = jim_target_mw,
4287
		.help = "Write 16-bit half-word(s) to target memory",
4288
		.usage = "address data [count]",
4289
4290
4291
4292
	},
	{
		.name = "mwb",
		.mode = COMMAND_EXEC,
4293
		.jim_handler = jim_target_mw,
4294
		.help = "Write byte(s) to target memory",
4295
		.usage = "address data [count]",
4296
4297
4298
4299
	},
	{
		.name = "mdw",
		.mode = COMMAND_EXEC,
4300
		.jim_handler = jim_target_md,
4301
		.help = "Display target memory as 32-bit words",
4302
		.usage = "address [count]",
4303
4304
4305
4306
	},
	{
		.name = "mdh",
		.mode = COMMAND_EXEC,
4307
		.jim_handler = jim_target_md,
4308
		.help = "Display target memory as 16-bit half-words",
4309
		.usage = "address [count]",
4310
4311
4312
4313
	},
	{
		.name = "mdb",
		.mode = COMMAND_EXEC,
4314
		.jim_handler = jim_target_md,
4315
		.help = "Display target memory as 8-bit bytes",
4316
		.usage = "address [count]",
4317
4318
4319
4320
	},
	{
		.name = "array2mem",
		.mode = COMMAND_EXEC,
4321
4322
4323
4324
		.jim_handler = jim_target_array2mem,
		.help = "Writes Tcl array of 8/16/32 bit numbers "
			"to target memory",
		.usage = "arrayname bitwidth address count",
4325
4326
4327
4328
	},
	{
		.name = "mem2array",
		.mode = COMMAND_EXEC,
4329
4330
4331
4332
		.jim_handler = jim_target_mem2array,
		.help = "Loads Tcl array of 8/16/32 bit numbers "
			"from target memory",
		.usage = "arrayname bitwidth address count",
4333
4334
4335
4336
	},
	{
		.name = "eventlist",
		.mode = COMMAND_EXEC,
4337
4338
		.jim_handler = jim_target_event_list,
		.help = "displays a table of events defined for this target",
4339
4340
4341
4342
	},
	{
		.name = "curstate",
		.mode = COMMAND_EXEC,
4343
4344
		.jim_handler = jim_target_current_state,
		.help = "displays the current state of this target",
4345
4346
4347
4348
	},
	{
		.name = "arp_examine",
		.mode = COMMAND_EXEC,
4349
4350
		.jim_handler = jim_target_examine,
		.help = "used internally for reset processing",
4351
	},
4352
4353
4354
4355
4356
4357
	{
		.name = "arp_halt_gdb",
		.mode = COMMAND_EXEC,
		.jim_handler = jim_target_halt_gdb,
		.help = "used internally for reset processing to halt GDB",
	},
4358
4359
4360
	{
		.name = "arp_poll",
		.mode = COMMAND_EXEC,
4361
4362
		.jim_handler = jim_target_poll,
		.help = "used internally for reset processing",
4363
4364
4365
4366
	},
	{
		.name = "arp_reset",
		.mode = COMMAND_EXEC,
4367
4368
		.jim_handler = jim_target_reset,
		.help = "used internally for reset processing",
4369
4370
4371
4372
	},
	{
		.name = "arp_halt",
		.mode = COMMAND_EXEC,
4373
4374
		.jim_handler = jim_target_halt,
		.help = "used internally for reset processing",
4375
4376
4377
4378
	},
	{
		.name = "arp_waitstate",
		.mode = COMMAND_EXEC,
4379
4380
		.jim_handler = jim_target_wait_state,
		.help = "used internally for reset processing",
4381
4382
4383
4384
	},
	{
		.name = "invoke-event",
		.mode = COMMAND_EXEC,
4385
4386
4387
		.jim_handler = jim_target_invoke_event,
		.help = "invoke handler for specified event",
		.usage = "event_name",
4388
4389
4390
4391
	},
	COMMAND_REGISTRATION_DONE
};

4392
static int target_create(Jim_GetOptInfo *goi)
4393
{
4394
4395
4396
4397
4398
4399
	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
4400
	struct target *target;
4401
	struct command_context *cmd_ctx;
4402
4403

	cmd_ctx = Jim_GetAssocData(goi->interp, "context");
zwelch's avatar
zwelch committed
4404
	if (goi->argc < 3) {
4405
		Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
4406
4407
4408
4409
		return JIM_ERR;
	}

	/* COMMAND */
4410
	Jim_GetOpt_Obj(goi, &new_cmd);
4411
	/* does this command exist? */
4412
	cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
zwelch's avatar
zwelch committed
4413
	if (cmd) {
4414
		cp = Jim_GetString(new_cmd, NULL);
4415
4416
4417
		Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
		return JIM_ERR;
	}
4418

4419
	/* TYPE */
4420
	e = Jim_GetOpt_String(goi, &cp2, NULL);
4421
4422
	cp = cp2;
	/* now does target type exist */
zwelch's avatar
zwelch committed
4423
4424
	for (x = 0 ; target_types[x] ; x++) {
		if (0 == strcmp(cp, target_types[x]->name)) {
4425
4426
4427
4428
			/* found */
			break;
		}
	}
zwelch's avatar
zwelch committed
4429
	if (target_types[x] == NULL) {
4430
		Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp);
zwelch's avatar
zwelch committed
4431
4432
		for (x = 0 ; target_types[x] ; x++) {
			if (target_types[x + 1]) {
4433
				Jim_AppendStrings(goi->interp,
4434
4435
4436
4437
								   Jim_GetResult(goi->interp),
								   target_types[x]->name,
								   ", ", NULL);
			} else {
4438
				Jim_AppendStrings(goi->interp,
4439
4440
								   Jim_GetResult(goi->interp),
								   " or ",
4441
								   target_types[x]->name,NULL);
4442
4443
4444
4445
4446
4447
			}
		}
		return JIM_ERR;
	}

	/* Create it */
Zachary T Welch's avatar
Zachary T Welch committed
4448
	target = calloc(1,sizeof(struct target));
4449
4450
4451
4452
	/* set target number */
	target->target_number = new_target_number();

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

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

4457
4458
4459
4460
4461
4462
4463
	/* 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;
4464

4465
4466
4467
4468
4469
4470
4471
	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;
4472

4473
4474
	target->display             = 1;

4475
4476
	target->halt_issued			= false;

4477
	/* initialize trace information */
Zachary T Welch's avatar
Zachary T Welch committed
4478
	target->trace_info = malloc(sizeof(struct trace));
4479
4480
4481
4482
4483
4484
4485
	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;
4486

4487
4488
4489
4490
4491
4492
4493
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

	/* Do the rest as "configure" options */
	goi->isconfigure = 1;
4494
	e = target_configure(goi, target);
4495
4496
4497

	if (target->tap == NULL)
	{
4498
		Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
zwelch's avatar
zwelch committed
4499
		e = JIM_ERR;
4500
4501
	}

zwelch's avatar
zwelch committed
4502
	if (e != JIM_OK) {
4503
4504
		free(target->type);
		free(target);
4505
4506
4507
		return e;
	}

zwelch's avatar
zwelch committed
4508
	if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
4509
4510
4511
4512
		/* default endian to little if not specified */
		target->endianness = TARGET_LITTLE_ENDIAN;
	}

4513
4514
4515
	/* incase variant is not set */
	if (!target->variant)
		target->variant = strdup("");
4516

4517
4518
4519
	cp = Jim_GetString(new_cmd, NULL);
	target->cmd_name = strdup(cp);

4520
	/* create the target specific commands */
4521
4522
4523
4524
	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);
4525
	}
zwelch's avatar
zwelch committed
4526
	if (target->type->target_create) {
4527
		(*(target->type->target_create))(target, goi->interp);
4528
4529
4530
4531
	}

	/* append to end of list */
	{
Zachary T Welch's avatar
Zachary T Welch committed
4532
		struct target **tpp;
4533
		tpp = &(all_targets);
zwelch's avatar
zwelch committed
4534
		while (*tpp) {
4535
			tpp = &((*tpp)->next);
4536
4537
4538
		}
		*tpp = target;
	}
4539

4540
	/* now - create the new target name command */
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
	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
4558
	};
4559
4560
4561
4562
4563
4564
4565
4566
4567
	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;
4568
4569
}

4570
static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4571
{
4572
4573
4574
4575
4576
4577
4578
4579
4580
	if (argc != 1)
	{
		Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
		return JIM_ERR;
	}
	struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
	Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1);
	return JIM_OK;
}
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
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;
}
4597

4598
4599
4600
4601
4602
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");
4603
4604
		return JIM_ERR;
	}
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
	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;
}
4615

4616
4617
4618
4619
4620
4621
4622
4623
4624
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;
4625
	}
4626
4627
	return target_create(&goi);
}
4628

4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
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>");
4639
		return JIM_ERR;
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
	}
	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)
4650
			continue;
4651
4652

		Jim_SetResultString(goi.interp, target_name(target), -1);
4653
4654
		return JIM_OK;
	}
4655
4656
	Jim_SetResult_sprintf(goi.interp,
			"Target: number %d does not exist", (int)(w));
4657
	return JIM_ERR;
4658
}
4659

4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
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[] = {
4679
4680
4681
	{
		.name = "init",
		.mode = COMMAND_CONFIG,
4682
		.handler = handle_target_init_command,
4683
4684
		.help = "initialize targets",
	},
4685
4686
	{
		.name = "create",
4687
		/* REVISIT this should be COMMAND_CONFIG ... */
4688
		.mode = COMMAND_ANY,
4689
4690
4691
		.jim_handler = jim_target_create,
		.usage = "name type '-chain-position' name [options ...]",
		.help = "Creates and selects a new target",
4692
4693
4694
4695
	},
	{
		.name = "current",
		.mode = COMMAND_ANY,
4696
		.jim_handler = jim_target_current,
4697
4698
4699
4700
4701
		.help = "Returns the currently selected target",
	},
	{
		.name = "types",
		.mode = COMMAND_ANY,
4702
4703
4704
		.jim_handler = jim_target_types,
		.help = "Returns the available target types as "
				"a list of strings",
4705
4706
4707
4708
	},
	{
		.name = "names",
		.mode = COMMAND_ANY,
4709
		.jim_handler = jim_target_names,
4710
4711
4712
4713
4714
		.help = "Returns the names of all targets as a list of strings",
	},
	{
		.name = "number",
		.mode = COMMAND_ANY,
4715
4716
4717
4718
		.jim_handler = jim_target_number,
		.usage = "number",
		.help = "Returns the name of the numbered target "
			"(DEPRECATED)",
4719
4720
4721
4722
	},
	{
		.name = "count",
		.mode = COMMAND_ANY,
4723
4724
4725
		.jim_handler = jim_target_count,
		.help = "Returns the number of targets as an integer "
			"(DEPRECATED)",
4726
4727
4728
4729
	},
	COMMAND_REGISTRATION_DONE
};

4730
4731
struct FastLoad
{
4732
	uint32_t address;
4733
	uint8_t *data;
4734
4735
4736
4737
4738
4739
4740
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

4741
static void free_fastload(void)
4742
{
zwelch's avatar
zwelch committed
4743
	if (fastload != NULL)
4744
4745
	{
		int i;
zwelch's avatar
zwelch committed
4746
		for (i = 0; i < fastload_num; i++)
4747
4748
4749
4750
4751
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
zwelch's avatar
zwelch committed
4752
		fastload = NULL;
4753
4754
4755
4756
4757
4758
	}
}




4759
COMMAND_HANDLER(handle_fast_load_image_command)
4760
{
4761
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
4762
	size_t buf_cnt;
4763
	uint32_t image_size;
zwelch's avatar
zwelch committed
4764
4765
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
4766
4767
	int i;

Zachary T Welch's avatar
Zachary T Welch committed
4768
	struct image image;
4769

4770
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
4771
4772
4773
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;
4774

Zachary T Welch's avatar
Zachary T Welch committed
4775
4776
	struct duration bench;
	duration_start(&bench);
4777

4778
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
4779
4780
4781
4782
4783
4784
	{
		return ERROR_OK;
	}

	image_size = 0x0;
	retval = ERROR_OK;
zwelch's avatar
zwelch committed
4785
4786
	fastload_num = image.num_sections;
	fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
zwelch's avatar
zwelch committed
4787
	if (fastload == NULL)
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
	{
		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)
		{
4798
			command_print(CMD_CTX, "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
4799
						  (int)(image.sections[i].size));
4800
4801
4802
4803
4804
4805
4806
4807
4808
			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
4809
4810
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
4811
4812
4813
4814


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

zwelch's avatar
zwelch committed
4815
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
4816
				(image.sections[i].base_address < max_address))
4817
		{
zwelch's avatar
zwelch committed
4818
			if (image.sections[i].base_address < min_address)
4819
4820
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
4821
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
4822
				length -= offset;
4823
4824
			}

zwelch's avatar
zwelch committed
4825
			if (image.sections[i].base_address + buf_cnt > max_address)
4826
			{
zwelch's avatar
zwelch committed
4827
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
4828
4829
			}

zwelch's avatar
zwelch committed
4830
			fastload[i].address = image.sections[i].base_address + offset;
zwelch's avatar
zwelch committed
4831
			fastload[i].data = malloc(length);
zwelch's avatar
zwelch committed
4832
			if (fastload[i].data == NULL)
4833
4834
4835
4836
			{
				free(buffer);
				break;
			}
zwelch's avatar
zwelch committed
4837
			memcpy(fastload[i].data, buffer + offset, length);
zwelch's avatar
zwelch committed
4838
			fastload[i].length = length;
4839
4840

			image_size += length;
4841
			command_print(CMD_CTX, "%u bytes written at address 0x%8.8x",
4842
						  (unsigned int)length,
zwelch's avatar
zwelch committed
4843
						  ((unsigned int)(image.sections[i].base_address + offset)));
4844
4845
4846
4847
4848
		}

		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
4849
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
4850
	{
4851
		command_print(CMD_CTX, "Loaded %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
4852
4853
4854
				"in %fs (%0.3f kb/s)", image_size, 
				duration_elapsed(&bench), duration_kbps(&bench, image_size));

4855
		command_print(CMD_CTX,
Zachary T Welch's avatar
Zachary T Welch committed
4856
4857
				"WARNING: image has not been loaded to target!"
				"You can issue a 'fast_load' to finish loading.");
4858
4859
4860
4861
	}

	image_close(&image);

zwelch's avatar
zwelch committed
4862
	if (retval != ERROR_OK)
4863
4864
4865
4866
4867
4868
4869
	{
		free_fastload();
	}

	return retval;
}

4870
COMMAND_HANDLER(handle_fast_load_command)
4871
{
4872
	if (CMD_ARGC > 0)
4873
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
4874
	if (fastload == NULL)
4875
4876
4877
4878
4879
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
zwelch's avatar
zwelch committed
4880
4881
4882
	int ms = timeval_ms();
	int size = 0;
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
4883
	for (i = 0; i < fastload_num;i++)
4884
	{
4885
4886
		struct target *target = get_current_target(CMD_CTX);
		command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x",
4887
					  (unsigned int)(fastload[i].address),
duane's avatar
duane committed
4888
					  (unsigned int)(fastload[i].length));
zwelch's avatar
zwelch committed
4889
		if (retval == ERROR_OK)
4890
		{
oharboe's avatar
oharboe committed
4891
			retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
4892
		}
zwelch's avatar
zwelch committed
4893
		size += fastload[i].length;
4894
	}
zwelch's avatar
zwelch committed
4895
	int after = timeval_ms();
4896
	command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
oharboe's avatar
oharboe committed
4897
	return retval;
4898
}
duane's avatar
duane committed
4899

4900
4901
4902
static const struct command_registration target_command_handlers[] = {
	{
		.name = "targets",
4903
		.handler = handle_targets_command,
4904
		.mode = COMMAND_ANY,
4905
4906
4907
		.help = "change current default target (one parameter) "
			"or prints table of all targets (no parameters)",
		.usage = "[target]",
4908
	},
4909
4910
4911
4912
	{
		.name = "target",
		.mode = COMMAND_CONFIG,
		.help = "configure target",
4913
4914

		.chain = target_subcommand_handlers,
4915
	},
4916
4917
4918
	COMMAND_REGISTRATION_DONE
};

4919
int target_register_commands(struct command_context *cmd_ctx)
4920
{
4921
	return register_commands(cmd_ctx, NULL, target_command_handlers);
4922
4923
}

Øyvind Harboe's avatar
Øyvind Harboe committed
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
static bool target_reset_nag = true;

bool get_target_reset_nag(void)
{
	return target_reset_nag;
}

COMMAND_HANDLER(handle_target_reset_nag)
{
	return CALL_COMMAND_HANDLER(handle_command_parse_bool,
			&target_reset_nag, "Nag after each reset about options to improve "
			"performance");
}

4938
4939
4940
static const struct command_registration target_exec_command_handlers[] = {
	{
		.name = "fast_load_image",
4941
		.handler = handle_fast_load_image_command,
4942
		.mode = COMMAND_ANY,
4943
4944
4945
4946
		.help = "Load image into server memory for later use by "
			"fast_load; primarily for profiling",
		.usage = "filename address ['bin'|'ihex'|'elf'|'s19'] "
			"[min_address [max_length]]",
4947
4948
4949
	},
	{
		.name = "fast_load",
4950
		.handler = handle_fast_load_command,
4951
		.mode = COMMAND_EXEC,
4952
4953
4954
4955
4956
		.help = "loads active fast load image to current target "
			"- mainly for profiling purposes",
	},
	{
		.name = "profile",
4957
		.handler = handle_profile_command,
4958
4959
4960
4961
4962
4963
		.mode = COMMAND_EXEC,
		.help = "profiling samples the CPU PC",
	},
	/** @todo don't register virt2phys() unless target supports it */
	{
		.name = "virt2phys",
4964
		.handler = handle_virt2phys_command,
4965
4966
		.mode = COMMAND_ANY,
		.help = "translate a virtual address into a physical address",
David Brownell's avatar
David Brownell committed
4967
		.usage = "virtual_address",
4968
4969
4970
	},
	{
		.name = "reg",
4971
		.handler = handle_reg_command,
4972
		.mode = COMMAND_EXEC,
4973
4974
4975
		.help = "display or set a register; with no arguments, "
			"displays all registers and their values",
		.usage = "[(register_name|register_number) [value]]",
4976
4977
4978
	},
	{
		.name = "poll",
4979
		.handler = handle_poll_command,
4980
		.mode = COMMAND_EXEC,
4981
4982
		.help = "poll target state; or reconfigure background polling",
		.usage = "['on'|'off']",
4983
4984
4985
	},
	{
		.name = "wait_halt",
4986
		.handler = handle_wait_halt_command,
4987
		.mode = COMMAND_EXEC,
4988
4989
4990
		.help = "wait up to the specified number of milliseconds "
			"(default 5) for a previously requested halt",
		.usage = "[milliseconds]",
4991
4992
4993
	},
	{
		.name = "halt",
4994
		.handler = handle_halt_command,
4995
		.mode = COMMAND_EXEC,
4996
4997
4998
		.help = "request target to halt, then wait up to the specified"
			"number of milliseconds (default 5) for it to complete",
		.usage = "[milliseconds]",
4999
5000
	},
	{
For faster browsing, not all history is shown. View entire blame