target.c 127 KB
Newer Older
4001
	else if (strcasecmp(cmd_name, "mwh") == 0) {
Øyvind Harboe's avatar
Øyvind Harboe committed
4002
		data_size = 2;
4003
4004
	}
	else if (strcasecmp(cmd_name, "mwb") == 0) {
Øyvind Harboe's avatar
Øyvind Harboe committed
4005
		data_size = 1;
4006
4007
4008
4009
	} else {
		LOG_ERROR("command '%s' unknown: ", cmd_name);
		return JIM_ERR;
	}
4010

Øyvind Harboe's avatar
Øyvind Harboe committed
4011
	return (target_fill_mem(target, a, target_write_memory_fast, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR;
4012
}
4013

4014
4015
4016
static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	const char *cmd_name = Jim_GetString(argv[0], NULL);
4017

4018
4019
	Jim_GetOptInfo goi;
	Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
4020

4021
4022
4023
4024
	/* danger! goi.argc will be modified below! */
	argc = goi.argc;

	if ((argc != 1) && (argc != 2))
4025
4026
4027
4028
4029
	{
		Jim_SetResult_sprintf(goi.interp,
				"usage: %s <address> [<count>]", cmd_name);
		return JIM_ERR;
	}
4030

4031
4032
4033
4034
4035
4036
	jim_wide a;
	int e = Jim_GetOpt_Wide(&goi, &a);
	if (e != JIM_OK) {
		return JIM_ERR;
	}
	jim_wide c;
4037
	if (argc == 2) {
4038
		e = Jim_GetOpt_Wide(&goi, &c);
zwelch's avatar
zwelch committed
4039
		if (e != JIM_OK) {
4040
4041
			return JIM_ERR;
		}
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
	} else {
		c = 1;
	}
	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;
4067
		}
4068
4069
4070
4071
		e = target_read_memory(target, a, b, y / b, target_buf);
		if (e != ERROR_OK) {
			Jim_SetResult_sprintf(interp, "error reading target @ 0x%08lx", (int)(a));
			return JIM_ERR;
4072
4073
		}

4074
4075
4076
4077
4078
		Jim_fprintf(interp, interp->cookie_stdout, "0x%08x ", (int)(a));
		switch (b) {
		case 4:
			for (x = 0; x < 16 && x < y; x += 4)
			{
4079
				z = target_buffer_get_u32(target, &(target_buf[ x ]));
4080
				Jim_fprintf(interp, interp->cookie_stdout, "%08x ", (int)(z));
4081
			}
4082
4083
			for (; (x < 16) ; x += 4) {
				Jim_fprintf(interp, interp->cookie_stdout, "         ");
4084
			}
4085
4086
4087
4088
			break;
		case 2:
			for (x = 0; x < 16 && x < y; x += 2)
			{
4089
				z = target_buffer_get_u16(target, &(target_buf[ x ]));
4090
				Jim_fprintf(interp, interp->cookie_stdout, "%04x ", (int)(z));
4091
			}
4092
4093
			for (; (x < 16) ; x += 2) {
				Jim_fprintf(interp, interp->cookie_stdout, "     ");
4094
			}
4095
4096
4097
4098
			break;
		case 1:
		default:
			for (x = 0 ; (x < 16) && (x < y) ; x += 1) {
4099
				z = target_buffer_get_u8(target, &(target_buf[ x ]));
4100
				Jim_fprintf(interp, interp->cookie_stdout, "%02x ", (int)(z));
4101
			}
4102
4103
			for (; (x < 16) ; x += 1) {
				Jim_fprintf(interp, interp->cookie_stdout, "   ");
4104
			}
4105
			break;
4106
		}
4107
4108
4109
4110
4111
4112
4113
4114
4115
		/* 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] = '.';
			}
4116
		}
4117
4118
4119
4120
		/* space pad  */
		while (x < 16) {
			target_buf[x] = ' ';
			x++;
4121
		}
4122
4123
4124
4125
4126
4127
4128
		/* terminate */
		target_buf[16] = 0;
		/* print - with a newline */
		Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf);
		/* NEXT... */
		c -= 16;
		a += 16;
4129
	}
4130
4131
4132
	return JIM_OK;
}

4133
4134
static int jim_target_mem2array(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv)
4135
4136
4137
4138
4139
{
	struct target *target = Jim_CmdPrivData(interp);
	return target_mem2array(interp, target, argc - 1, argv + 1);
}

4140
4141
static int jim_target_array2mem(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv)
4142
4143
4144
4145
{
	struct target *target = Jim_CmdPrivData(interp);
	return target_array2mem(interp, target, argc - 1, argv + 1);
}
zwelch's avatar
zwelch committed
4146

4147
4148
static int jim_target_tap_disabled(Jim_Interp *interp)
{
zwelch's avatar
zwelch committed
4149
4150
	Jim_SetResult_sprintf(interp, "[TAP is disabled]");
	return JIM_ERR;
4151
4152
}

4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
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;
}

4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
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;
}

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
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
4241
4242
4243
4244
4245
	if (!(target_was_examined(target)))
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_TARGET_NOT_EXAMINED;
	}
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
4294
4295
4296
4297
4298
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
4378
4379
4380
	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,
4381
		.jim_handler = jim_target_configure,
4382
		.help  = "configure a new target for use",
4383
		.usage = "[target_attribute ...]",
4384
4385
4386
4387
	},
	{
		.name = "cget",
		.mode = COMMAND_ANY,
4388
4389
4390
		.jim_handler = jim_target_configure,
		.help  = "returns the specified target attribute",
		.usage = "target_attribute",
4391
4392
4393
4394
	},
	{
		.name = "mww",
		.mode = COMMAND_EXEC,
4395
		.jim_handler = jim_target_mw,
4396
		.help = "Write 32-bit word(s) to target memory",
4397
		.usage = "address data [count]",
4398
4399
4400
4401
	},
	{
		.name = "mwh",
		.mode = COMMAND_EXEC,
4402
		.jim_handler = jim_target_mw,
4403
		.help = "Write 16-bit half-word(s) to target memory",
4404
		.usage = "address data [count]",
4405
4406
4407
4408
	},
	{
		.name = "mwb",
		.mode = COMMAND_EXEC,
4409
		.jim_handler = jim_target_mw,
4410
		.help = "Write byte(s) to target memory",
4411
		.usage = "address data [count]",
4412
4413
4414
4415
	},
	{
		.name = "mdw",
		.mode = COMMAND_EXEC,
4416
		.jim_handler = jim_target_md,
4417
		.help = "Display target memory as 32-bit words",
4418
		.usage = "address [count]",
4419
4420
4421
4422
	},
	{
		.name = "mdh",
		.mode = COMMAND_EXEC,
4423
		.jim_handler = jim_target_md,
4424
		.help = "Display target memory as 16-bit half-words",
4425
		.usage = "address [count]",
4426
4427
4428
4429
	},
	{
		.name = "mdb",
		.mode = COMMAND_EXEC,
4430
		.jim_handler = jim_target_md,
4431
		.help = "Display target memory as 8-bit bytes",
4432
		.usage = "address [count]",
4433
4434
4435
4436
	},
	{
		.name = "array2mem",
		.mode = COMMAND_EXEC,
4437
4438
4439
4440
		.jim_handler = jim_target_array2mem,
		.help = "Writes Tcl array of 8/16/32 bit numbers "
			"to target memory",
		.usage = "arrayname bitwidth address count",
4441
4442
4443
4444
	},
	{
		.name = "mem2array",
		.mode = COMMAND_EXEC,
4445
4446
4447
4448
		.jim_handler = jim_target_mem2array,
		.help = "Loads Tcl array of 8/16/32 bit numbers "
			"from target memory",
		.usage = "arrayname bitwidth address count",
4449
4450
4451
4452
	},
	{
		.name = "eventlist",
		.mode = COMMAND_EXEC,
4453
4454
		.jim_handler = jim_target_event_list,
		.help = "displays a table of events defined for this target",
4455
4456
4457
4458
	},
	{
		.name = "curstate",
		.mode = COMMAND_EXEC,
4459
4460
		.jim_handler = jim_target_current_state,
		.help = "displays the current state of this target",
4461
4462
4463
4464
	},
	{
		.name = "arp_examine",
		.mode = COMMAND_EXEC,
4465
4466
		.jim_handler = jim_target_examine,
		.help = "used internally for reset processing",
4467
	},
4468
4469
4470
4471
4472
4473
	{
		.name = "arp_halt_gdb",
		.mode = COMMAND_EXEC,
		.jim_handler = jim_target_halt_gdb,
		.help = "used internally for reset processing to halt GDB",
	},
4474
4475
4476
	{
		.name = "arp_poll",
		.mode = COMMAND_EXEC,
4477
4478
		.jim_handler = jim_target_poll,
		.help = "used internally for reset processing",
4479
4480
4481
4482
	},
	{
		.name = "arp_reset",
		.mode = COMMAND_EXEC,
4483
4484
		.jim_handler = jim_target_reset,
		.help = "used internally for reset processing",
4485
4486
4487
4488
	},
	{
		.name = "arp_halt",
		.mode = COMMAND_EXEC,
4489
4490
		.jim_handler = jim_target_halt,
		.help = "used internally for reset processing",
4491
4492
4493
4494
	},
	{
		.name = "arp_waitstate",
		.mode = COMMAND_EXEC,
4495
4496
		.jim_handler = jim_target_wait_state,
		.help = "used internally for reset processing",
4497
4498
4499
4500
	},
	{
		.name = "invoke-event",
		.mode = COMMAND_EXEC,
4501
4502
4503
		.jim_handler = jim_target_invoke_event,
		.help = "invoke handler for specified event",
		.usage = "event_name",
4504
4505
4506
4507
	},
	COMMAND_REGISTRATION_DONE
};

4508
static int target_create(Jim_GetOptInfo *goi)
4509
{
4510
4511
4512
4513
4514
4515
	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
4516
	struct target *target;
4517
	struct command_context *cmd_ctx;
4518
4519

	cmd_ctx = Jim_GetAssocData(goi->interp, "context");
zwelch's avatar
zwelch committed
4520
	if (goi->argc < 3) {
4521
		Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
4522
4523
4524
4525
		return JIM_ERR;
	}

	/* COMMAND */
4526
	Jim_GetOpt_Obj(goi, &new_cmd);
4527
	/* does this command exist? */
4528
	cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
zwelch's avatar
zwelch committed
4529
	if (cmd) {
4530
		cp = Jim_GetString(new_cmd, NULL);
4531
4532
4533
		Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
		return JIM_ERR;
	}
4534

4535
	/* TYPE */
4536
	e = Jim_GetOpt_String(goi, &cp2, NULL);
4537
4538
	cp = cp2;
	/* now does target type exist */
zwelch's avatar
zwelch committed
4539
4540
	for (x = 0 ; target_types[x] ; x++) {
		if (0 == strcmp(cp, target_types[x]->name)) {
4541
4542
4543
4544
			/* found */
			break;
		}
	}
zwelch's avatar
zwelch committed
4545
	if (target_types[x] == NULL) {
4546
		Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp);
zwelch's avatar
zwelch committed
4547
4548
		for (x = 0 ; target_types[x] ; x++) {
			if (target_types[x + 1]) {
4549
				Jim_AppendStrings(goi->interp,
4550
4551
4552
4553
								   Jim_GetResult(goi->interp),
								   target_types[x]->name,
								   ", ", NULL);
			} else {
4554
				Jim_AppendStrings(goi->interp,
4555
4556
								   Jim_GetResult(goi->interp),
								   " or ",
4557
								   target_types[x]->name,NULL);
4558
4559
4560
4561
4562
4563
			}
		}
		return JIM_ERR;
	}

	/* Create it */
Zachary T Welch's avatar
Zachary T Welch committed
4564
	target = calloc(1,sizeof(struct target));
4565
4566
4567
4568
	/* set target number */
	target->target_number = new_target_number();

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

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

4573
4574
4575
4576
4577
4578
4579
	/* 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;
4580

4581
4582
4583
4584
4585
4586
4587
	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;
4588

4589
4590
	target->display             = 1;

4591
4592
	target->halt_issued			= false;

4593
	/* initialize trace information */
Zachary T Welch's avatar
Zachary T Welch committed
4594
	target->trace_info = malloc(sizeof(struct trace));
4595
4596
4597
4598
4599
4600
4601
	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;
4602

4603
4604
4605
4606
4607
4608
4609
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

	/* Do the rest as "configure" options */
	goi->isconfigure = 1;
4610
	e = target_configure(goi, target);
4611
4612
4613

	if (target->tap == NULL)
	{
4614
		Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
zwelch's avatar
zwelch committed
4615
		e = JIM_ERR;
4616
4617
	}

zwelch's avatar
zwelch committed
4618
	if (e != JIM_OK) {
4619
4620
		free(target->type);
		free(target);
4621
4622
4623
		return e;
	}

zwelch's avatar
zwelch committed
4624
	if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
4625
4626
4627
4628
		/* default endian to little if not specified */
		target->endianness = TARGET_LITTLE_ENDIAN;
	}

4629
4630
4631
	/* incase variant is not set */
	if (!target->variant)
		target->variant = strdup("");
4632

4633
4634
4635
	cp = Jim_GetString(new_cmd, NULL);
	target->cmd_name = strdup(cp);

4636
	/* create the target specific commands */
4637
4638
4639
4640
	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);
4641
	}
zwelch's avatar
zwelch committed
4642
	if (target->type->target_create) {
4643
		(*(target->type->target_create))(target, goi->interp);
4644
4645
4646
4647
	}

	/* append to end of list */
	{
Zachary T Welch's avatar
Zachary T Welch committed
4648
		struct target **tpp;
4649
		tpp = &(all_targets);
zwelch's avatar
zwelch committed
4650
		while (*tpp) {
4651
			tpp = &((*tpp)->next);
4652
4653
4654
		}
		*tpp = target;
	}
4655

4656
	/* now - create the new target name command */
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
	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
4674
	};
4675
4676
4677
4678
4679
4680
4681
4682
4683
	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;
4684
4685
}

4686
static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4687
{
4688
4689
4690
4691
4692
4693
4694
4695
4696
	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;
}
4697

4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
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;
}
4713

4714
4715
4716
4717
4718
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");
4719
4720
		return JIM_ERR;
	}
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
	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;
}
4731

4732
4733
4734
4735
4736
4737
4738
4739
4740
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;
4741
	}
4742
4743
	return target_create(&goi);
}
4744

4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
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>");
4755
		return JIM_ERR;
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
	}
	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)
4766
			continue;
4767
4768

		Jim_SetResultString(goi.interp, target_name(target), -1);
4769
4770
		return JIM_OK;
	}
4771
4772
	Jim_SetResult_sprintf(goi.interp,
			"Target: number %d does not exist", (int)(w));
4773
	return JIM_ERR;
4774
}
4775

4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
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[] = {
4795
4796
4797
	{
		.name = "init",
		.mode = COMMAND_CONFIG,
4798
		.handler = handle_target_init_command,
4799
4800
		.help = "initialize targets",
	},
4801
4802
	{
		.name = "create",
4803
		/* REVISIT this should be COMMAND_CONFIG ... */
4804
		.mode = COMMAND_ANY,
4805
4806
4807
		.jim_handler = jim_target_create,
		.usage = "name type '-chain-position' name [options ...]",
		.help = "Creates and selects a new target",
4808
4809
4810
4811
	},
	{
		.name = "current",
		.mode = COMMAND_ANY,
4812
		.jim_handler = jim_target_current,
4813
4814
4815
4816
4817
		.help = "Returns the currently selected target",
	},
	{
		.name = "types",
		.mode = COMMAND_ANY,
4818
4819
4820
		.jim_handler = jim_target_types,
		.help = "Returns the available target types as "
				"a list of strings",
4821
4822
4823
4824
	},
	{
		.name = "names",
		.mode = COMMAND_ANY,
4825
		.jim_handler = jim_target_names,
4826
4827
4828
4829
4830
		.help = "Returns the names of all targets as a list of strings",
	},
	{
		.name = "number",
		.mode = COMMAND_ANY,
4831
4832
4833
4834
		.jim_handler = jim_target_number,
		.usage = "number",
		.help = "Returns the name of the numbered target "
			"(DEPRECATED)",
4835
4836
4837
4838
	},
	{
		.name = "count",
		.mode = COMMAND_ANY,
4839
4840
4841
		.jim_handler = jim_target_count,
		.help = "Returns the number of targets as an integer "
			"(DEPRECATED)",
4842
4843
4844
4845
	},
	COMMAND_REGISTRATION_DONE
};

4846
4847
struct FastLoad
{
4848
	uint32_t address;
4849
	uint8_t *data;
4850
4851
4852
4853
4854
4855
4856
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

4857
static void free_fastload(void)
4858
{
zwelch's avatar
zwelch committed
4859
	if (fastload != NULL)
4860
4861
	{
		int i;
zwelch's avatar
zwelch committed
4862
		for (i = 0; i < fastload_num; i++)
4863
4864
4865
4866
4867
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
zwelch's avatar
zwelch committed
4868
		fastload = NULL;
4869
4870
4871
4872
4873
4874
	}
}




4875
COMMAND_HANDLER(handle_fast_load_image_command)
4876
{
4877
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
4878
	size_t buf_cnt;
4879
	uint32_t image_size;
zwelch's avatar
zwelch committed
4880
4881
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
4882
4883
	int i;

Zachary T Welch's avatar
Zachary T Welch committed
4884
	struct image image;
4885

4886
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
4887
4888
4889
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;
4890

Zachary T Welch's avatar
Zachary T Welch committed
4891
4892
	struct duration bench;
	duration_start(&bench);
4893

4894
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
4895
4896
4897
4898
4899
4900
	{
		return ERROR_OK;
	}

	image_size = 0x0;
	retval = ERROR_OK;
zwelch's avatar
zwelch committed
4901
4902
	fastload_num = image.num_sections;
	fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
zwelch's avatar
zwelch committed
4903
	if (fastload == NULL)
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
	{
		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)
		{
4914
			command_print(CMD_CTX, "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
4915
						  (int)(image.sections[i].size));
4916
4917
4918
4919
4920
4921
4922
4923
4924
			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
4925
4926
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
4927
4928
4929
4930


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

zwelch's avatar
zwelch committed
4931
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
4932
				(image.sections[i].base_address < max_address))
4933
		{
zwelch's avatar
zwelch committed
4934
			if (image.sections[i].base_address < min_address)
4935
4936
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
4937
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
4938
				length -= offset;
4939
4940
			}

zwelch's avatar
zwelch committed
4941
			if (image.sections[i].base_address + buf_cnt > max_address)
4942
			{
zwelch's avatar
zwelch committed
4943
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
4944
4945
			}

zwelch's avatar
zwelch committed
4946
			fastload[i].address = image.sections[i].base_address + offset;
zwelch's avatar
zwelch committed
4947
			fastload[i].data = malloc(length);
zwelch's avatar
zwelch committed
4948
			if (fastload[i].data == NULL)
4949
4950
4951
4952
			{
				free(buffer);
				break;
			}
zwelch's avatar
zwelch committed
4953
			memcpy(fastload[i].data, buffer + offset, length);
zwelch's avatar
zwelch committed
4954
			fastload[i].length = length;
4955
4956

			image_size += length;
4957
			command_print(CMD_CTX, "%u bytes written at address 0x%8.8x",
4958
						  (unsigned int)length,
zwelch's avatar
zwelch committed
4959
						  ((unsigned int)(image.sections[i].base_address + offset)));
4960
4961
4962
4963
4964
		}

		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
4965
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
4966
	{
4967
		command_print(CMD_CTX, "Loaded %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
4968
4969
4970
				"in %fs (%0.3f kb/s)", image_size, 
				duration_elapsed(&bench), duration_kbps(&bench, image_size));

4971
		command_print(CMD_CTX,
Zachary T Welch's avatar
Zachary T Welch committed
4972
4973
				"WARNING: image has not been loaded to target!"
				"You can issue a 'fast_load' to finish loading.");
4974
4975
4976
4977
	}

	image_close(&image);

zwelch's avatar
zwelch committed
4978
	if (retval != ERROR_OK)
4979
4980
4981
4982
4983
4984
4985
	{
		free_fastload();
	}

	return retval;
}

4986
COMMAND_HANDLER(handle_fast_load_command)
4987
{
4988
	if (CMD_ARGC > 0)
4989
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
4990
	if (fastload == NULL)
4991
4992
4993
4994
4995
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
zwelch's avatar
zwelch committed
4996
4997
4998
	int ms = timeval_ms();
	int size = 0;
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
4999
	for (i = 0; i < fastload_num;i++)
5000
	{
For faster browsing, not all history is shown. View entire blame