target.c 128 KB
Newer Older
2001
		reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1);
oharboe's avatar
oharboe committed
2002

2003
2004
		if (!reg)
		{
2005
			command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
2006
2007
2008
2009
2010
			return ERROR_OK;
		}
	}

	/* display a register */
2011
	if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9'))))
2012
	{
2013
		if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
2014
			reg->valid = 0;
oharboe's avatar
oharboe committed
2015

2016
2017
		if (reg->valid == 0)
		{
2018
			reg->type->get(reg);
2019
2020
		}
		value = buf_to_str(reg->value, reg->size, 16);
2021
		command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
2022
2023
2024
		free(value);
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2025

2026
	/* set register value */
2027
	if (CMD_ARGC == 2)
2028
	{
Zachary T Welch's avatar
Zachary T Welch committed
2029
		uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
2030
		str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0);
2031

2032
		reg->type->set(reg, buf);
oharboe's avatar
oharboe committed
2033

2034
		value = buf_to_str(reg->value, reg->size, 16);
2035
		command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
2036
		free(value);
oharboe's avatar
oharboe committed
2037

2038
		free(buf);
oharboe's avatar
oharboe committed
2039

2040
2041
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2042

2043
	command_print(CMD_CTX, "usage: reg <#|name> [value]");
oharboe's avatar
oharboe committed
2044

2045
2046
2047
	return ERROR_OK;
}

2048
COMMAND_HANDLER(handle_poll_command)
2049
{
2050
	int retval = ERROR_OK;
2051
	struct target *target = get_current_target(CMD_CTX);
2052

2053
	if (CMD_ARGC == 0)
2054
	{
2055
		command_print(CMD_CTX, "background polling: %s",
2056
				jtag_poll_get_enabled() ? "on" : "off");
2057
		command_print(CMD_CTX, "TAP: %s (%s)",
zwelch's avatar
zwelch committed
2058
2059
2060
2061
				target->tap->dotted_name,
				target->tap->enabled ? "enabled" : "disabled");
		if (!target->tap->enabled)
			return ERROR_OK;
2062
		if ((retval = target_poll(target)) != ERROR_OK)
2063
			return retval;
2064
		if ((retval = target_arch_state(target)) != ERROR_OK)
2065
			return retval;
2066
	}
2067
	else if (CMD_ARGC == 1)
2068
	{
2069
2070
2071
2072
2073
		bool enable;
		COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
		jtag_poll_set_enabled(enable);
	}
	else
2074
2075
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
2076
	}
oharboe's avatar
oharboe committed
2077

2078
	return retval;
2079
2080
}

2081
COMMAND_HANDLER(handle_wait_halt_command)
2082
{
2083
	if (CMD_ARGC > 1)
2084
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2085

2086
	unsigned ms = 5000;
2087
	if (1 == CMD_ARGC)
2088
	{
2089
		int retval = parse_uint(CMD_ARGV[0], &ms);
2090
		if (ERROR_OK != retval)
2091
		{
2092
			command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME);
2093
			return ERROR_COMMAND_SYNTAX_ERROR;
2094
		}
2095
2096
		// convert seconds (given) to milliseconds (needed)
		ms *= 1000;
2097
2098
	}

2099
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2100
	return target_wait_state(target, TARGET_HALTED, ms);
2101
2102
}

2103
2104
2105
2106
2107
2108
/* wait for target state to change. The trick here is to have a low
 * latency for short waits and not to suck up all the CPU time
 * on longer waits.
 *
 * After 500ms, keep_alive() is invoked
 */
Zachary T Welch's avatar
Zachary T Welch committed
2109
int target_wait_state(struct target *target, enum target_state state, int ms)
2110
2111
{
	int retval;
zwelch's avatar
zwelch committed
2112
2113
	long long then = 0, cur;
	int once = 1;
oharboe's avatar
oharboe committed
2114

2115
2116
	for (;;)
	{
zwelch's avatar
zwelch committed
2117
		if ((retval = target_poll(target)) != ERROR_OK)
2118
2119
2120
2121
2122
			return retval;
		if (target->state == state)
		{
			break;
		}
2123
		cur = timeval_ms();
2124
2125
		if (once)
		{
zwelch's avatar
zwelch committed
2126
			once = 0;
2127
			then = timeval_ms();
2128
			LOG_DEBUG("waiting for target %s...",
2129
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
2130
		}
oharboe's avatar
oharboe committed
2131

zwelch's avatar
zwelch committed
2132
		if (cur-then > 500)
2133
2134
2135
2136
		{
			keep_alive();
		}

zwelch's avatar
zwelch committed
2137
		if ((cur-then) > ms)
2138
		{
2139
			LOG_ERROR("timed out while waiting for target %s",
2140
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
oharboe's avatar
oharboe committed
2141
			return ERROR_FAIL;
2142
2143
		}
	}
oharboe's avatar
oharboe committed
2144

2145
2146
2147
	return ERROR_OK;
}

2148
COMMAND_HANDLER(handle_halt_command)
2149
{
2150
	LOG_DEBUG("-");
2151

2152
	struct target *target = get_current_target(CMD_CTX);
2153
2154
	int retval = target_halt(target);
	if (ERROR_OK != retval)
2155
		return retval;
oharboe's avatar
oharboe committed
2156

2157
	if (CMD_ARGC == 1)
2158
	{
2159
2160
		unsigned wait_local;
		retval = parse_uint(CMD_ARGV[0], &wait_local);
2161
2162
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
2163
		if (!wait_local)
2164
2165
2166
			return ERROR_OK;
	}

2167
	return CALL_COMMAND_HANDLER(handle_wait_halt_command);
2168
2169
}

2170
COMMAND_HANDLER(handle_soft_reset_halt_command)
2171
{
2172
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2173

2174
	LOG_USER("requesting target halt and executing a soft reset");
oharboe's avatar
oharboe committed
2175

oharboe's avatar
   
oharboe committed
2176
	target->type->soft_reset_halt(target);
oharboe's avatar
oharboe committed
2177

2178
2179
2180
	return ERROR_OK;
}

2181
COMMAND_HANDLER(handle_reset_command)
2182
{
2183
	if (CMD_ARGC > 1)
2184
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2185

2186
	enum target_reset_mode reset_mode = RESET_RUN;
2187
	if (CMD_ARGC == 1)
2188
	{
2189
		const Jim_Nvp *n;
2190
		n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
zwelch's avatar
zwelch committed
2191
		if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) {
oharboe's avatar
oharboe committed
2192
			return ERROR_COMMAND_SYNTAX_ERROR;
2193
		}
2194
		reset_mode = n->value;
2195
	}
oharboe's avatar
oharboe committed
2196

2197
	/* reset *all* targets */
2198
	return target_process_reset(CMD_CTX, reset_mode);
2199
2200
}

2201

2202
COMMAND_HANDLER(handle_resume_command)
2203
{
2204
	int current = 1;
2205
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2206
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2207

2208
	struct target *target = get_current_target(CMD_CTX);
zwelch's avatar
zwelch committed
2209
	target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
oharboe's avatar
oharboe committed
2210

2211
2212
	/* with no CMD_ARGV, resume from current pc, addr = 0,
	 * with one arguments, addr = CMD_ARGV[0],
zwelch's avatar
zwelch committed
2213
	 * handle breakpoints, not debugging */
2214
	uint32_t addr = 0;
2215
	if (CMD_ARGC == 1)
2216
	{
2217
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
2218
		current = 0;
2219
	}
oharboe's avatar
oharboe committed
2220

2221
	return target_resume(target, current, addr, 1, 0);
2222
2223
}

2224
COMMAND_HANDLER(handle_step_command)
2225
{
2226
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2227
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2228

2229
	LOG_DEBUG("-");
oharboe's avatar
oharboe committed
2230

2231
2232
	/* with no CMD_ARGV, step from current pc, addr = 0,
	 * with one argument addr = CMD_ARGV[0],
zwelch's avatar
zwelch committed
2233
	 * handle breakpoints, debugging */
2234
	uint32_t addr = 0;
2235
	int current_pc = 1;
2236
	if (CMD_ARGC == 1)
2237
	{
2238
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
2239
		current_pc = 0;
2240
	}
oharboe's avatar
oharboe committed
2241

2242
	struct target *target = get_current_target(CMD_CTX);
2243
2244

	return target->type->step(target, current_pc, addr, 1);
2245
2246
}

2247
static void handle_md_output(struct command_context *cmd_ctx,
Zachary T Welch's avatar
Zachary T Welch committed
2248
		struct target *target, uint32_t address, unsigned size,
2249
		unsigned count, const uint8_t *buffer)
2250
2251
2252
2253
2254
2255
2256
2257
2258
{
	const unsigned line_bytecnt = 32;
	unsigned line_modulo = line_bytecnt / size;

	char output[line_bytecnt * 4 + 1];
	unsigned output_len = 0;

	const char *value_fmt;
	switch (size) {
2259
	case 4: value_fmt = "%8.8x "; break;
2260
	case 2: value_fmt = "%4.4x "; break;
2261
	case 1: value_fmt = "%2.2x "; break;
2262
	default:
2263
		/* "can't happen", caller checked */
2264
		LOG_ERROR("invalid memory read size: %u", size);
2265
		return;
2266
	}
2267

2268
2269
2270
2271
2272
2273
	for (unsigned i = 0; i < count; i++)
	{
		if (i % line_modulo == 0)
		{
			output_len += snprintf(output + output_len,
					sizeof(output) - output_len,
2274
					"0x%8.8x: ",
duane's avatar
duane committed
2275
					(unsigned)(address + (i*size)));
2276
		}
2277

zwelch's avatar
zwelch committed
2278
		uint32_t value = 0;
2279
		const uint8_t *value_ptr = buffer + i * size;
2280
2281
2282
2283
2284
2285
2286
2287
		switch (size) {
		case 4: value = target_buffer_get_u32(target, value_ptr); break;
		case 2: value = target_buffer_get_u16(target, value_ptr); break;
		case 1: value = *value_ptr;
		}
		output_len += snprintf(output + output_len,
				sizeof(output) - output_len,
				value_fmt, value);
2288

2289
2290
2291
2292
2293
2294
2295
		if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
		{
			command_print(cmd_ctx, "%s", output);
			output_len = 0;
		}
	}
}
2296

2297
COMMAND_HANDLER(handle_md_command)
2298
{
2299
	if (CMD_ARGC < 1)
2300
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2301

2302
	unsigned size = 0;
2303
	switch (CMD_NAME[2]) {
2304
2305
2306
2307
	case 'w': size = 4; break;
	case 'h': size = 2; break;
	case 'b': size = 1; break;
	default: return ERROR_COMMAND_SYNTAX_ERROR;
2308
2309
	}

2310
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Zachary T Welch's avatar
Zachary T Welch committed
2311
	int (*fn)(struct target *target,
2312
2313
2314
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	if (physical)
	{
2315
		CMD_ARGC--;
2316
		CMD_ARGV++;
2317
2318
2319
2320
2321
		fn=target_read_phys_memory;
	} else
	{
		fn=target_read_memory;
	}
2322
	if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
2323
2324
2325
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2326

2327
	uint32_t address;
2328
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
oharboe's avatar
oharboe committed
2329

2330
	unsigned count = 1;
2331
	if (CMD_ARGC == 2)
2332
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
oharboe's avatar
oharboe committed
2333

2334
	uint8_t *buffer = calloc(count, size);
oharboe's avatar
oharboe committed
2335

2336
	struct target *target = get_current_target(CMD_CTX);
2337
	int retval = fn(target, address, size, count, buffer);
2338
	if (ERROR_OK == retval)
2339
		handle_md_output(CMD_CTX, target, address, size, count, buffer);
2340
2341

	free(buffer);
oharboe's avatar
oharboe committed
2342

oharboe's avatar
oharboe committed
2343
	return retval;
2344
2345
}

Øyvind Harboe's avatar
Øyvind Harboe committed
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
typedef int (*target_write_fn)(struct target *target,
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);

static int target_write_memory_fast(struct target *target,
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target_write_buffer(target, address, size * count, buffer);
}

static int target_fill_mem(struct target *target,
		uint32_t address,
		target_write_fn fn,
		unsigned data_size,
		/* value */
		uint32_t b,
		/* count */
		unsigned c)
{
	/* We have to write in reasonably large chunks to be able
	 * to fill large memory areas with any sane speed */
	const unsigned chunk_size = 16384;
	uint8_t *target_buf = malloc(chunk_size * data_size);
	if (target_buf == NULL)
	{
		LOG_ERROR("Out of memory");
		return ERROR_FAIL;
	}

	for (unsigned i = 0; i < chunk_size; i ++)
	{
		switch (data_size)
		{
		case 4:
			target_buffer_set_u32(target, target_buf + i*data_size, b);
			break;
		case 2:
			target_buffer_set_u16(target, target_buf + i*data_size, b);
			break;
		case 1:
			target_buffer_set_u8(target, target_buf + i*data_size, b);
			break;
		default:
			exit(-1);
		}
	}

	int retval = ERROR_OK;

	for (unsigned x = 0; x < c; x += chunk_size)
	{
		unsigned current;
		current = c - x;
		if (current > chunk_size)
		{
			current = chunk_size;
		}
2402
		retval = fn(target, address + x * data_size, data_size, current, target_buf);
Øyvind Harboe's avatar
Øyvind Harboe committed
2403
2404
2405
2406
		if (retval != ERROR_OK)
		{
			break;
		}
2407
2408
		/* avoid GDB timeouts */
		keep_alive();
Øyvind Harboe's avatar
Øyvind Harboe committed
2409
2410
2411
2412
2413
2414
2415
	}
	free(target_buf);

	return retval;
}


2416
COMMAND_HANDLER(handle_mw_command)
2417
{
2418
	if (CMD_ARGC < 2)
2419
2420
2421
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2422
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Øyvind Harboe's avatar
Øyvind Harboe committed
2423
	target_write_fn fn;
2424
2425
	if (physical)
	{
2426
		CMD_ARGC--;
2427
		CMD_ARGV++;
2428
2429
2430
		fn=target_write_phys_memory;
	} else
	{
Øyvind Harboe's avatar
Øyvind Harboe committed
2431
		fn = target_write_memory_fast;
2432
	}
2433
	if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
oharboe's avatar
oharboe committed
2434
		return ERROR_COMMAND_SYNTAX_ERROR;
2435

2436
	uint32_t address;
2437
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
2438

2439
	uint32_t value;
2440
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
2441
2442

	unsigned count = 1;
2443
	if (CMD_ARGC == 3)
2444
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
oharboe's avatar
oharboe committed
2445

2446
	struct target *target = get_current_target(CMD_CTX);
2447
	unsigned wordsize;
2448
	switch (CMD_NAME[2])
2449
2450
	{
		case 'w':
oharboe's avatar
oharboe committed
2451
			wordsize = 4;
2452
2453
			break;
		case 'h':
oharboe's avatar
oharboe committed
2454
			wordsize = 2;
2455
2456
			break;
		case 'b':
oharboe's avatar
oharboe committed
2457
			wordsize = 1;
2458
2459
			break;
		default:
oharboe's avatar
oharboe committed
2460
			return ERROR_COMMAND_SYNTAX_ERROR;
2461
2462
	}

Øyvind Harboe's avatar
Øyvind Harboe committed
2463
	return target_fill_mem(target, address, fn, wordsize, value, count);
2464
2465
}

2466
static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
2467
		uint32_t *min_address, uint32_t *max_address)
2468
{
2469
	if (CMD_ARGC < 1 || CMD_ARGC > 5)
2470
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2471

2472
2473
	/* a base address isn't always necessary,
	 * default to 0x0 (i.e. don't relocate) */
2474
	if (CMD_ARGC >= 2)
2475
	{
2476
		uint32_t addr;
2477
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2478
2479
		image->base_address = addr;
		image->base_address_set = 1;
2480
2481
	}
	else
2482
		image->base_address_set = 0;
oharboe's avatar
oharboe committed
2483

2484
	image->start_address_set = 0;
oharboe's avatar
oharboe committed
2485

2486
	if (CMD_ARGC >= 4)
2487
	{
2488
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
2489
	}
2490
	if (CMD_ARGC == 5)
2491
	{
2492
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
2493
		// use size (given) to find max (required)
2494
		*max_address += *min_address;
2495
	}
oharboe's avatar
oharboe committed
2496

2497
	if (*min_address > *max_address)
2498
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2499

2500
2501
2502
	return ERROR_OK;
}

2503
COMMAND_HANDLER(handle_load_image_command)
2504
{
2505
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2506
	size_t buf_cnt;
2507
2508
2509
	uint32_t image_size;
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
2510
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2511
	struct image image;
2512

2513
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
2514
2515
2516
2517
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;

2518
	struct target *target = get_current_target(CMD_CTX);
Zachary T Welch's avatar
Zachary T Welch committed
2519
2520
2521

	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2522

2523
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
2524
2525
2526
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2527

2528
	image_size = 0x0;
2529
	retval = ERROR_OK;
2530
2531
2532
2533
2534
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2535
			command_print(CMD_CTX,
2536
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2537
						  (int)(image.sections[i].size));
2538
2539
			break;
		}
oharboe's avatar
oharboe committed
2540

2541
2542
2543
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2544
2545
			break;
		}
oharboe's avatar
oharboe committed
2546

zwelch's avatar
zwelch committed
2547
2548
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
oharboe's avatar
oharboe committed
2549

2550
		/* DANGER!!! beware of unsigned comparision here!!! */
oharboe's avatar
oharboe committed
2551

zwelch's avatar
zwelch committed
2552
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
2553
				(image.sections[i].base_address < max_address))
2554
		{
zwelch's avatar
zwelch committed
2555
			if (image.sections[i].base_address < min_address)
2556
2557
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
2558
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
2559
				length -= offset;
2560
			}
oharboe's avatar
oharboe committed
2561

zwelch's avatar
zwelch committed
2562
			if (image.sections[i].base_address + buf_cnt > max_address)
2563
			{
zwelch's avatar
zwelch committed
2564
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
2565
			}
oharboe's avatar
oharboe committed
2566

zwelch's avatar
zwelch committed
2567
			if ((retval = target_write_buffer(target, image.sections[i].base_address + offset, length, buffer + offset)) != ERROR_OK)
2568
2569
2570
2571
2572
			{
				free(buffer);
				break;
			}
			image_size += length;
2573
			command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
2574
						  (unsigned int)length,
zwelch's avatar
zwelch committed
2575
						  image.sections[i].base_address + offset);
2576
		}
oharboe's avatar
oharboe committed
2577

2578
2579
2580
		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
2581
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2582
	{
2583
		command_print(CMD_CTX, "downloaded %" PRIu32 " bytes "
2584
				"in %fs (%0.3f KiB/s)", image_size,
Zachary T Welch's avatar
Zachary T Welch committed
2585
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2586
2587
	}

2588
2589
	image_close(&image);

2590
	return retval;
2591
2592
2593

}

2594
COMMAND_HANDLER(handle_dump_image_command)
2595
{
Zachary T Welch's avatar
Zachary T Welch committed
2596
	struct fileio fileio;
oharboe's avatar
oharboe committed
2597

2598
	uint8_t buffer[560];
2599
	int retvaltemp;
oharboe's avatar
oharboe committed
2600
2601


2602
	struct target *target = get_current_target(CMD_CTX);
2603

2604
	if (CMD_ARGC != 3)
2605
	{
2606
		command_print(CMD_CTX, "usage: dump_image <filename> <address> <size>");
2607
2608
2609
		return ERROR_OK;
	}

2610
	uint32_t address;
2611
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address);
2612
	uint32_t size;
2613
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size);
2614

2615
	if (fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
2616
2617
2618
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2619

Zachary T Welch's avatar
Zachary T Welch committed
2620
2621
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2622

2623
	int retval = ERROR_OK;
2624
2625
	while (size > 0)
	{
Zachary T Welch's avatar
Zachary T Welch committed
2626
		size_t size_written;
2627
		uint32_t this_run_size = (size > 560) ? 560 : size;
2628
		retval = target_read_buffer(target, address, this_run_size, buffer);
2629
2630
2631
2632
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2633

2634
2635
2636
2637
2638
		retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2639

2640
2641
2642
2643
		size -= this_run_size;
		address += this_run_size;
	}

zwelch's avatar
zwelch committed
2644
	if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
2645
2646
		return retvaltemp;

Zachary T Welch's avatar
Zachary T Welch committed
2647
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2648
	{
2649
		command_print(CMD_CTX,
2650
				"dumped %ld bytes in %fs (%0.3f KiB/s)", (long)fileio.size,
Zachary T Welch's avatar
Zachary T Welch committed
2651
				duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
2652
	}
oharboe's avatar
oharboe committed
2653

2654
	return retval;
2655
2656
}

2657
static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
2658
{
2659
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2660
	size_t buf_cnt;
2661
	uint32_t image_size;
2662
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2663
	int retval;
2664
2665
	uint32_t checksum = 0;
	uint32_t mem_checksum = 0;
2666

Zachary T Welch's avatar
Zachary T Welch committed
2667
	struct image image;
oharboe's avatar
oharboe committed
2668

2669
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2670

2671
	if (CMD_ARGC < 1)
2672
	{
2673
		return ERROR_COMMAND_SYNTAX_ERROR;
2674
	}
oharboe's avatar
oharboe committed
2675

2676
2677
	if (!target)
	{
2678
		LOG_ERROR("no target selected");
2679
		return ERROR_FAIL;
2680
	}
oharboe's avatar
oharboe committed
2681

Zachary T Welch's avatar
Zachary T Welch committed
2682
2683
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2684

2685
	if (CMD_ARGC >= 2)
2686
	{
2687
		uint32_t addr;
2688
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2689
		image.base_address = addr;
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
		image.base_address_set = 1;
	}
	else
	{
		image.base_address_set = 0;
		image.base_address = 0x0;
	}

	image.start_address_set = 0;

2700
	if ((retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL)) != ERROR_OK)
2701
	{
2702
		return retval;
2703
	}
oharboe's avatar
oharboe committed
2704

2705
	image_size = 0x0;
2706
	int diffs = 0;
zwelch's avatar
zwelch committed
2707
	retval = ERROR_OK;
2708
2709
2710
2711
2712
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2713
			command_print(CMD_CTX,
2714
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2715
						  (int)(image.sections[i].size));
2716
2717
2718
2719
2720
			break;
		}
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2721
			break;
2722
		}
oharboe's avatar
oharboe committed
2723

oharboe's avatar
oharboe committed
2724
		if (verify)
2725
		{
oharboe's avatar
oharboe committed
2726
			/* calculate checksum of image */
2727
2728
2729
2730
2731
2732
			retval = image_calculate_checksum(buffer, buf_cnt, &checksum);
			if (retval != ERROR_OK)
			{
				free(buffer);
				break;
			}
oharboe's avatar
oharboe committed
2733

oharboe's avatar
oharboe committed
2734
			retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
2735
			if (retval != ERROR_OK)
drath's avatar