target.c 117 KB
Newer Older
4001
4002
4003
4004
		} else {
			c = 1;
		}
		b = 1; /* shut up gcc */
zwelch's avatar
zwelch committed
4005
		switch (n->value) {
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
		case TS_CMD_MDW:
			b =  4;
			break;
		case TS_CMD_MDH:
			b = 2;
			break;
		case TS_CMD_MDB:
			b = 1;
			break;
		}

		/* convert to "bytes" */
		c = c * b;
		/* count is now in 'BYTES' */
zwelch's avatar
zwelch committed
4020
		while (c > 0) {
4021
			y = c;
zwelch's avatar
zwelch committed
4022
			if (y > 16) {
4023
4024
				y = 16;
			}
4025
			e = target_read_memory(target, a, b, y / b, target_buf);
zwelch's avatar
zwelch committed
4026
			if (e != ERROR_OK) {
4027
				Jim_SetResult_sprintf(interp, "error reading target @ 0x%08lx", (int)(a));
4028
4029
				return JIM_ERR;
			}
4030

4031
			Jim_fprintf(interp, interp->cookie_stdout, "0x%08x ", (int)(a));
zwelch's avatar
zwelch committed
4032
			switch (b) {
4033
			case 4:
zwelch's avatar
zwelch committed
4034
				for (x = 0 ; (x < 16) && (x < y) ; x += 4) {
4035
4036
					z = target_buffer_get_u32(target, &(target_buf[ x * 4 ]));
					Jim_fprintf(interp, interp->cookie_stdout, "%08x ", (int)(z));
4037
				}
zwelch's avatar
zwelch committed
4038
				for (; (x < 16) ; x += 4) {
4039
					Jim_fprintf(interp, interp->cookie_stdout, "         ");
4040
4041
4042
				}
				break;
			case 2:
zwelch's avatar
zwelch committed
4043
				for (x = 0 ; (x < 16) && (x < y) ; x += 2) {
4044
4045
					z = target_buffer_get_u16(target, &(target_buf[ x * 2 ]));
					Jim_fprintf(interp, interp->cookie_stdout, "%04x ", (int)(z));
4046
				}
zwelch's avatar
zwelch committed
4047
				for (; (x < 16) ; x += 2) {
4048
					Jim_fprintf(interp, interp->cookie_stdout, "     ");
4049
4050
4051
4052
				}
				break;
			case 1:
			default:
zwelch's avatar
zwelch committed
4053
				for (x = 0 ; (x < 16) && (x < y) ; x += 1) {
4054
4055
					z = target_buffer_get_u8(target, &(target_buf[ x * 4 ]));
					Jim_fprintf(interp, interp->cookie_stdout, "%02x ", (int)(z));
4056
				}
zwelch's avatar
zwelch committed
4057
				for (; (x < 16) ; x += 1) {
4058
					Jim_fprintf(interp, interp->cookie_stdout, "   ");
4059
4060
4061
4062
				}
				break;
			}
			/* ascii-ify the bytes */
zwelch's avatar
zwelch committed
4063
			for (x = 0 ; x < y ; x++) {
4064
				if ((target_buf[x] >= 0x20) &&
zwelch's avatar
zwelch committed
4065
					(target_buf[x] <= 0x7e)) {
4066
4067
4068
4069
4070
4071
4072
					/* good */
				} else {
					/* smack it */
					target_buf[x] = '.';
				}
			}
			/* space pad  */
zwelch's avatar
zwelch committed
4073
			while (x < 16) {
4074
4075
4076
4077
4078
4079
				target_buf[x] = ' ';
				x++;
			}
			/* terminate */
			target_buf[16] = 0;
			/* print - with a newline */
4080
			Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf);
4081
4082
4083
4084
4085
4086
			/* NEXT... */
			c -= 16;
			a += 16;
		}
		return JIM_OK;
	case TS_CMD_MEM2ARRAY:
4087
		return target_mem2array(goi.interp, target, goi.argc, goi.argv);
4088
4089
		break;
	case TS_CMD_ARRAY2MEM:
4090
		return target_array2mem(goi.interp, target, goi.argc, goi.argv);
4091
4092
		break;
	case TS_CMD_EXAMINE:
zwelch's avatar
zwelch committed
4093
		if (goi.argc) {
4094
			Jim_WrongNumArgs(goi.interp, 2, argv, "[no parameters]");
4095
4096
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4097
4098
		if (!target->tap->enabled)
			goto err_tap_disabled;
4099
		e = target->type->examine(target);
zwelch's avatar
zwelch committed
4100
		if (e != ERROR_OK) {
4101
			Jim_SetResult_sprintf(interp, "examine-fails: %d", e);
4102
4103
4104
4105
			return JIM_ERR;
		}
		return JIM_OK;
	case TS_CMD_POLL:
zwelch's avatar
zwelch committed
4106
		if (goi.argc) {
4107
			Jim_WrongNumArgs(goi.interp, 2, argv, "[no parameters]");
4108
4109
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4110
4111
		if (!target->tap->enabled)
			goto err_tap_disabled;
zwelch's avatar
zwelch committed
4112
		if (!(target_was_examined(target))) {
4113
4114
			e = ERROR_TARGET_NOT_EXAMINED;
		} else {
4115
			e = target->type->poll(target);
4116
		}
zwelch's avatar
zwelch committed
4117
		if (e != ERROR_OK) {
4118
			Jim_SetResult_sprintf(interp, "poll-fails: %d", e);
4119
4120
4121
4122
4123
4124
			return JIM_ERR;
		} else {
			return JIM_OK;
		}
		break;
	case TS_CMD_RESET:
zwelch's avatar
zwelch committed
4125
		if (goi.argc != 2) {
4126
4127
			Jim_WrongNumArgs(interp, 2, argv,
					"([tT]|[fF]|assert|deassert) BOOL");
4128
4129
			return JIM_ERR;
		}
4130
		e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n);
zwelch's avatar
zwelch committed
4131
		if (e != JIM_OK) {
4132
			Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1);
4133
4134
			return e;
		}
4135
		/* the halt or not param */
4136
		e = Jim_GetOpt_Wide(&goi, &a);
zwelch's avatar
zwelch committed
4137
		if (e != JIM_OK) {
4138
4139
			return e;
		}
zwelch's avatar
zwelch committed
4140
4141
		if (!target->tap->enabled)
			goto err_tap_disabled;
4142
4143
4144
4145
4146
4147
4148
		if (!target->type->assert_reset
				|| !target->type->deassert_reset) {
			Jim_SetResult_sprintf(interp,
					"No target-specific reset for %s",
					target->cmd_name);
			return JIM_ERR;
		}
4149
		/* determine if we should halt or not. */
4150
		target->reset_halt = !!a;
4151
		/* When this happens - all workareas are invalid. */
4152
4153
		target_free_all_working_areas_restore(target, 0);

4154
		/* do the assert */
zwelch's avatar
zwelch committed
4155
		if (n->value == NVP_ASSERT) {
4156
			e = target->type->assert_reset(target);
4157
		} else {
4158
			e = target->type->deassert_reset(target);
4159
		}
4160
		return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
4161
	case TS_CMD_HALT:
zwelch's avatar
zwelch committed
4162
		if (goi.argc) {
4163
			Jim_WrongNumArgs(goi.interp, 0, argv, "halt [no parameters]");
4164
4165
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4166
4167
		if (!target->tap->enabled)
			goto err_tap_disabled;
4168
4169
		e = target->type->halt(target);
		return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
4170
	case TS_CMD_WAITSTATE:
4171
		/* params:  <name>  statename timeoutmsecs */
zwelch's avatar
zwelch committed
4172
		if (goi.argc != 2) {
4173
			Jim_SetResult_sprintf(goi.interp, "%s STATENAME TIMEOUTMSECS", n->name);
4174
4175
			return JIM_ERR;
		}
4176
		e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n);
zwelch's avatar
zwelch committed
4177
		if (e != JIM_OK) {
4178
			Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1);
4179
4180
			return e;
		}
4181
		e = Jim_GetOpt_Wide(&goi, &a);
zwelch's avatar
zwelch committed
4182
		if (e != JIM_OK) {
4183
4184
			return e;
		}
zwelch's avatar
zwelch committed
4185
4186
		if (!target->tap->enabled)
			goto err_tap_disabled;
4187
		e = target_wait_state(target, n->value, a);
zwelch's avatar
zwelch committed
4188
		if (e != ERROR_OK) {
4189
			Jim_SetResult_sprintf(goi.interp,
4190
								   "target: %s wait %s fails (%d) %s",
4191
4192
								   target->cmd_name,
								   n->name,
4193
								   e, target_strerror_safe(e));
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
			return JIM_ERR;
		} else {
			return JIM_OK;
		}
	case TS_CMD_EVENTLIST:
		/* List for human, Events defined for this target.
		 * scripts/programs should use 'name cget -event NAME'
		 */
		{
			target_event_action_t *teap;
			teap = target->event_action;
4205
			command_print(cmd_ctx, "Event actions for target (%d) %s\n",
4206
						   target->target_number,
4207
						   target->cmd_name);
4208
4209
			command_print(cmd_ctx, "%-25s | Body", "Event");
			command_print(cmd_ctx, "------------------------- | ----------------------------------------");
zwelch's avatar
zwelch committed
4210
			while (teap) {
4211
				command_print(cmd_ctx,
4212
							   "%-25s | %s",
4213
4214
							   Jim_Nvp_value2name_simple(nvp_target_event, teap->event)->name,
							   Jim_GetString(teap->body, NULL));
4215
4216
				teap = teap->next;
			}
4217
			command_print(cmd_ctx, "***END***");
4218
4219
4220
			return JIM_OK;
		}
	case TS_CMD_CURSTATE:
zwelch's avatar
zwelch committed
4221
		if (goi.argc != 0) {
4222
			Jim_WrongNumArgs(goi.interp, 0, argv, "[no parameters]");
4223
4224
			return JIM_ERR;
		}
4225
		Jim_SetResultString(goi.interp,
4226
4227
							target_state_name( target ),
							-1);
4228
		return JIM_OK;
4229
	case TS_CMD_INVOKE_EVENT:
zwelch's avatar
zwelch committed
4230
		if (goi.argc != 1) {
4231
			Jim_SetResult_sprintf(goi.interp, "%s ?EVENTNAME?",n->name);
4232
4233
			return JIM_ERR;
		}
4234
		e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n);
zwelch's avatar
zwelch committed
4235
		if (e != JIM_OK) {
4236
			Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
4237
4238
			return e;
		}
4239
		target_handle_event(target, n->value);
4240
		return JIM_OK;
4241
4242
	}
	return JIM_ERR;
zwelch's avatar
zwelch committed
4243
4244
4245
4246

err_tap_disabled:
	Jim_SetResult_sprintf(interp, "[TAP is disabled]");
	return JIM_ERR;
4247
4248
}

4249
static int target_create(Jim_GetOptInfo *goi)
4250
{
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
	Jim_Obj *new_cmd;
	Jim_Cmd *cmd;
	const char *cp;
	char *cp2;
	int e;
	int x;
	target_t *target;
	struct command_context_s *cmd_ctx;

	cmd_ctx = Jim_GetAssocData(goi->interp, "context");
zwelch's avatar
zwelch committed
4261
	if (goi->argc < 3) {
4262
		Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
4263
4264
4265
4266
		return JIM_ERR;
	}

	/* COMMAND */
4267
	Jim_GetOpt_Obj(goi, &new_cmd);
4268
	/* does this command exist? */
4269
	cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
zwelch's avatar
zwelch committed
4270
	if (cmd) {
4271
		cp = Jim_GetString(new_cmd, NULL);
4272
4273
4274
		Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
		return JIM_ERR;
	}
4275

4276
	/* TYPE */
4277
	e = Jim_GetOpt_String(goi, &cp2, NULL);
4278
4279
	cp = cp2;
	/* now does target type exist */
zwelch's avatar
zwelch committed
4280
4281
	for (x = 0 ; target_types[x] ; x++) {
		if (0 == strcmp(cp, target_types[x]->name)) {
4282
4283
4284
4285
			/* found */
			break;
		}
	}
zwelch's avatar
zwelch committed
4286
	if (target_types[x] == NULL) {
4287
		Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp);
zwelch's avatar
zwelch committed
4288
4289
		for (x = 0 ; target_types[x] ; x++) {
			if (target_types[x + 1]) {
4290
				Jim_AppendStrings(goi->interp,
4291
4292
4293
4294
								   Jim_GetResult(goi->interp),
								   target_types[x]->name,
								   ", ", NULL);
			} else {
4295
				Jim_AppendStrings(goi->interp,
4296
4297
								   Jim_GetResult(goi->interp),
								   " or ",
4298
								   target_types[x]->name,NULL);
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
			}
		}
		return JIM_ERR;
	}

	/* Create it */
	target = calloc(1,sizeof(target_t));
	/* set target number */
	target->target_number = new_target_number();

	/* allocate memory for each unique target type */
	target->type = (target_type_t*)calloc(1,sizeof(target_type_t));

4312
	memcpy(target->type, target_types[x], sizeof(target_type_t));
4313

4314
4315
4316
4317
4318
4319
4320
	/* 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;
4321

4322
4323
4324
4325
4326
4327
4328
	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;
4329

4330
4331
	target->display             = 1;

4332
4333
	target->halt_issued			= false;

4334
4335
4336
4337
4338
4339
4340
4341
4342
	/* initialize trace information */
	target->trace_info = malloc(sizeof(trace_t));
	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;
4343

4344
4345
4346
4347
4348
4349
4350
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

	/* Do the rest as "configure" options */
	goi->isconfigure = 1;
4351
	e = target_configure(goi, target);
4352
4353
4354

	if (target->tap == NULL)
	{
4355
		Jim_SetResultString(interp, "-chain-position required when creating target", -1);
zwelch's avatar
zwelch committed
4356
		e = JIM_ERR;
4357
4358
	}

zwelch's avatar
zwelch committed
4359
	if (e != JIM_OK) {
4360
4361
		free(target->type);
		free(target);
4362
4363
4364
		return e;
	}

zwelch's avatar
zwelch committed
4365
	if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
4366
4367
4368
4369
		/* default endian to little if not specified */
		target->endianness = TARGET_LITTLE_ENDIAN;
	}

4370
4371
4372
	/* incase variant is not set */
	if (!target->variant)
		target->variant = strdup("");
4373

4374
	/* create the target specific commands */
zwelch's avatar
zwelch committed
4375
	if (target->type->register_commands) {
4376
		(*(target->type->register_commands))(cmd_ctx);
4377
	}
zwelch's avatar
zwelch committed
4378
	if (target->type->target_create) {
4379
		(*(target->type->target_create))(target, goi->interp);
4380
4381
4382
4383
4384
4385
	}

	/* append to end of list */
	{
		target_t **tpp;
		tpp = &(all_targets);
zwelch's avatar
zwelch committed
4386
		while (*tpp) {
4387
			tpp = &((*tpp)->next);
4388
4389
4390
4391
		}
		*tpp = target;
	}

4392
	cp = Jim_GetString(new_cmd, NULL);
4393
4394
4395
	target->cmd_name = strdup(cp);

	/* now - create the new target name command */
4396
	e = Jim_CreateCommand(goi->interp,
4397
4398
4399
4400
						   /* name */
						   cp,
						   tcl_target_func, /* C function */
						   target, /* private data */
4401
						   NULL); /* no del proc */
4402
4403
4404
4405

	return e;
}

4406
static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
{
	int x,r,e;
	jim_wide w;
	struct command_context_s *cmd_ctx;
	target_t *target;
	Jim_GetOptInfo goi;
	enum tcmd {
		/* TG = target generic */
		TG_CMD_CREATE,
		TG_CMD_TYPES,
		TG_CMD_NAMES,
		TG_CMD_CURRENT,
		TG_CMD_NUMBER,
		TG_CMD_COUNT,
	};
	const char *target_cmds[] = {
4423
		"create", "types", "names", "current", "number",
4424
		"count",
4425
		NULL /* terminate */
4426
4427
4428
	};

	LOG_DEBUG("Target command params:");
4429
	LOG_DEBUG("%s", Jim_Debug_ArgvString(interp, argc, argv));
4430

4431
	cmd_ctx = Jim_GetAssocData(interp, "context");
4432

4433
	Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
4434

zwelch's avatar
zwelch committed
4435
	if (goi.argc == 0) {
4436
4437
4438
4439
		Jim_WrongNumArgs(interp, 1, argv, "missing: command ...");
		return JIM_ERR;
	}

4440
4441
	/* Jim_GetOpt_Debug(&goi); */
	r = Jim_GetOpt_Enum(&goi, target_cmds, &x);
zwelch's avatar
zwelch committed
4442
	if (r != JIM_OK) {
4443
4444
4445
		return r;
	}

zwelch's avatar
zwelch committed
4446
	switch (x) {
4447
4448
4449
4450
	default:
		Jim_Panic(goi.interp,"Why am I here?");
		return JIM_ERR;
	case TG_CMD_CURRENT:
zwelch's avatar
zwelch committed
4451
		if (goi.argc != 0) {
4452
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4453
4454
			return JIM_ERR;
		}
4455
		Jim_SetResultString(goi.interp, get_current_target(cmd_ctx)->cmd_name, -1);
4456
4457
		return JIM_OK;
	case TG_CMD_TYPES:
zwelch's avatar
zwelch committed
4458
		if (goi.argc != 0) {
4459
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4460
4461
			return JIM_ERR;
		}
4462
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
zwelch's avatar
zwelch committed
4463
		for (x = 0 ; target_types[x] ; x++) {
4464
			Jim_ListAppendElement(goi.interp,
4465
								   Jim_GetResult(goi.interp),
4466
								   Jim_NewStringObj(goi.interp, target_types[x]->name, -1));
4467
4468
4469
		}
		return JIM_OK;
	case TG_CMD_NAMES:
zwelch's avatar
zwelch committed
4470
		if (goi.argc != 0) {
4471
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4472
4473
			return JIM_ERR;
		}
4474
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
4475
		target = all_targets;
zwelch's avatar
zwelch committed
4476
		while (target) {
4477
			Jim_ListAppendElement(goi.interp,
4478
								   Jim_GetResult(goi.interp),
4479
								   Jim_NewStringObj(goi.interp, target->cmd_name, -1));
4480
4481
			target = target->next;
		}
4482
		return JIM_OK;
4483
	case TG_CMD_CREATE:
zwelch's avatar
zwelch committed
4484
		if (goi.argc < 3) {
4485
			Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "?name  ... config options ...");
4486
4487
			return JIM_ERR;
		}
4488
		return target_create(&goi);
4489
4490
		break;
	case TG_CMD_NUMBER:
4491
4492
		/* It's OK to remove this mechanism sometime after August 2010 or so */
		LOG_WARNING("don't use numbers as target identifiers; use names");
zwelch's avatar
zwelch committed
4493
		if (goi.argc != 1) {
4494
			Jim_SetResult_sprintf(goi.interp, "expected: target number ?NUMBER?");
4495
4496
			return JIM_ERR;
		}
4497
		e = Jim_GetOpt_Wide(&goi, &w);
zwelch's avatar
zwelch committed
4498
		if (e != JIM_OK) {
4499
4500
			return JIM_ERR;
		}
4501
4502
4503
		for (x = 0, target = all_targets; target; target = target->next, x++) {
			if (target->target_number == w)
				break;
4504
		}
4505
4506
4507
4508
4509
4510
4511
		if (target == NULL) {
			Jim_SetResult_sprintf(goi.interp,
					"Target: number %d does not exist", (int)(w));
			return JIM_ERR;
		}
		Jim_SetResultString(goi.interp, target->cmd_name, -1);
		return JIM_OK;
4512
	case TG_CMD_COUNT:
zwelch's avatar
zwelch committed
4513
		if (goi.argc != 0) {
4514
			Jim_WrongNumArgs(goi.interp, 0, goi.argv, "<no parameters>");
4515
4516
			return JIM_ERR;
		}
4517
4518
4519
		for (x = 0, target = all_targets; target; target = target->next, x++)
			continue;
		Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, x));
4520
4521
		return JIM_OK;
	}
4522
4523

	return JIM_ERR;
4524
}
4525
4526
4527
4528


struct FastLoad
{
4529
	uint32_t address;
4530
	uint8_t *data;
4531
4532
4533
4534
4535
4536
4537
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

4538
static void free_fastload(void)
4539
{
zwelch's avatar
zwelch committed
4540
	if (fastload != NULL)
4541
4542
	{
		int i;
zwelch's avatar
zwelch committed
4543
		for (i = 0; i < fastload_num; i++)
4544
4545
4546
4547
4548
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
zwelch's avatar
zwelch committed
4549
		fastload = NULL;
4550
4551
4552
4553
4554
4555
	}
}




4556
static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4557
{
4558
	uint8_t *buffer;
4559
4560
	uint32_t buf_cnt;
	uint32_t image_size;
zwelch's avatar
zwelch committed
4561
4562
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
4563
4564
4565
4566
4567
4568
4569
	int i;

	image_t image;

	duration_t duration;
	char *duration_text;

4570
4571
4572
4573
	int retval = parse_load_image_command_args(args, argc,
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583

	duration_start_measure(&duration);

	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
	{
		return ERROR_OK;
	}

	image_size = 0x0;
	retval = ERROR_OK;
zwelch's avatar
zwelch committed
4584
4585
	fastload_num = image.num_sections;
	fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
zwelch's avatar
zwelch committed
4586
	if (fastload == NULL)
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
	{
		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)
		{
4597
			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
4598
						  (int)(image.sections[i].size));
4599
4600
4601
4602
4603
4604
4605
4606
4607
			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
4608
4609
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
4610
4611
4612
4613


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

zwelch's avatar
zwelch committed
4614
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
4615
				(image.sections[i].base_address < max_address))
4616
		{
zwelch's avatar
zwelch committed
4617
			if (image.sections[i].base_address < min_address)
4618
4619
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
4620
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
4621
				length -= offset;
4622
4623
			}

zwelch's avatar
zwelch committed
4624
			if (image.sections[i].base_address + buf_cnt > max_address)
4625
			{
zwelch's avatar
zwelch committed
4626
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
4627
4628
			}

zwelch's avatar
zwelch committed
4629
			fastload[i].address = image.sections[i].base_address + offset;
zwelch's avatar
zwelch committed
4630
			fastload[i].data = malloc(length);
zwelch's avatar
zwelch committed
4631
			if (fastload[i].data == NULL)
4632
4633
4634
4635
			{
				free(buffer);
				break;
			}
zwelch's avatar
zwelch committed
4636
			memcpy(fastload[i].data, buffer + offset, length);
zwelch's avatar
zwelch committed
4637
			fastload[i].length = length;
4638
4639

			image_size += length;
oharboe's avatar
oharboe committed
4640
			command_print(cmd_ctx, "%u bytes written at address 0x%8.8x",
4641
						  (unsigned int)length,
zwelch's avatar
zwelch committed
4642
						  ((unsigned int)(image.sections[i].base_address + offset)));
4643
4644
4645
4646
4647
4648
		}

		free(buffer);
	}

	duration_stop_measure(&duration, &duration_text);
zwelch's avatar
zwelch committed
4649
	if (retval == ERROR_OK)
4650
	{
duane's avatar
duane committed
4651
		command_print(cmd_ctx, "Loaded %u bytes in %s", (unsigned int)image_size, duration_text);
4652
4653
4654
4655
4656
4657
		command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
	}
	free(duration_text);

	image_close(&image);

zwelch's avatar
zwelch committed
4658
	if (retval != ERROR_OK)
4659
4660
4661
4662
4663
4664
4665
	{
		free_fastload();
	}

	return retval;
}

4666
static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4667
{
zwelch's avatar
zwelch committed
4668
	if (argc > 0)
4669
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
4670
	if (fastload == NULL)
4671
4672
4673
4674
4675
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
zwelch's avatar
zwelch committed
4676
4677
4678
	int ms = timeval_ms();
	int size = 0;
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
4679
	for (i = 0; i < fastload_num;i++)
4680
4681
	{
		target_t *target = get_current_target(cmd_ctx);
4682
4683
		command_print(cmd_ctx, "Write to 0x%08x, length 0x%08x",
					  (unsigned int)(fastload[i].address),
duane's avatar
duane committed
4684
					  (unsigned int)(fastload[i].length));
zwelch's avatar
zwelch committed
4685
		if (retval == ERROR_OK)
4686
		{
oharboe's avatar
oharboe committed
4687
			retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
4688
		}
zwelch's avatar
zwelch committed
4689
		size += fastload[i].length;
4690
	}
zwelch's avatar
zwelch committed
4691
	int after = timeval_ms();
4692
	command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
oharboe's avatar
oharboe committed
4693
	return retval;
4694
}
duane's avatar
duane committed
4695
4696
4697


/*
4698
 * Local Variables:
duane's avatar
duane committed
4699
4700
4701
4702
 * c-basic-offset: 4
 * tab-width: 4
 * End:
 */
For faster browsing, not all history is shown. View entire blame