target.c 127 KB
Newer Older
2001
		command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
2002
2003
2004
		free(value);
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2005

2006
	/* set register value */
2007
	if (CMD_ARGC == 2)
2008
	{
Zachary T Welch's avatar
Zachary T Welch committed
2009
		uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
2010
		str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0);
2011

2012
		reg->type->set(reg, buf);
oharboe's avatar
oharboe committed
2013

2014
		value = buf_to_str(reg->value, reg->size, 16);
2015
		command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
2016
		free(value);
oharboe's avatar
oharboe committed
2017

2018
		free(buf);
oharboe's avatar
oharboe committed
2019

2020
2021
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2022

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

2025
2026
2027
	return ERROR_OK;
}

2028
COMMAND_HANDLER(handle_poll_command)
2029
{
2030
	int retval = ERROR_OK;
2031
	struct target *target = get_current_target(CMD_CTX);
2032

2033
	if (CMD_ARGC == 0)
2034
	{
2035
		command_print(CMD_CTX, "background polling: %s",
2036
				jtag_poll_get_enabled() ? "on" : "off");
2037
		command_print(CMD_CTX, "TAP: %s (%s)",
zwelch's avatar
zwelch committed
2038
2039
2040
2041
				target->tap->dotted_name,
				target->tap->enabled ? "enabled" : "disabled");
		if (!target->tap->enabled)
			return ERROR_OK;
2042
		if ((retval = target_poll(target)) != ERROR_OK)
2043
			return retval;
2044
		if ((retval = target_arch_state(target)) != ERROR_OK)
2045
			return retval;
2046
	}
2047
	else if (CMD_ARGC == 1)
2048
	{
2049
2050
2051
2052
2053
		bool enable;
		COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
		jtag_poll_set_enabled(enable);
	}
	else
2054
2055
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
2056
	}
oharboe's avatar
oharboe committed
2057

2058
	return retval;
2059
2060
}

2061
COMMAND_HANDLER(handle_wait_halt_command)
2062
{
2063
	if (CMD_ARGC > 1)
2064
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2065

2066
	unsigned ms = 5000;
2067
	if (1 == CMD_ARGC)
2068
	{
2069
		int retval = parse_uint(CMD_ARGV[0], &ms);
2070
		if (ERROR_OK != retval)
2071
		{
2072
			command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME);
2073
			return ERROR_COMMAND_SYNTAX_ERROR;
2074
		}
2075
2076
		// convert seconds (given) to milliseconds (needed)
		ms *= 1000;
2077
2078
	}

2079
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2080
	return target_wait_state(target, TARGET_HALTED, ms);
2081
2082
}

2083
2084
2085
2086
2087
2088
/* 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
2089
int target_wait_state(struct target *target, enum target_state state, int ms)
2090
2091
{
	int retval;
zwelch's avatar
zwelch committed
2092
2093
	long long then = 0, cur;
	int once = 1;
oharboe's avatar
oharboe committed
2094

2095
2096
	for (;;)
	{
zwelch's avatar
zwelch committed
2097
		if ((retval = target_poll(target)) != ERROR_OK)
2098
2099
2100
2101
2102
			return retval;
		if (target->state == state)
		{
			break;
		}
2103
		cur = timeval_ms();
2104
2105
		if (once)
		{
zwelch's avatar
zwelch committed
2106
			once = 0;
2107
			then = timeval_ms();
2108
			LOG_DEBUG("waiting for target %s...",
2109
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
2110
		}
oharboe's avatar
oharboe committed
2111

zwelch's avatar
zwelch committed
2112
		if (cur-then > 500)
2113
2114
2115
2116
		{
			keep_alive();
		}

zwelch's avatar
zwelch committed
2117
		if ((cur-then) > ms)
2118
		{
2119
			LOG_ERROR("timed out while waiting for target %s",
2120
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
oharboe's avatar
oharboe committed
2121
			return ERROR_FAIL;
2122
2123
		}
	}
oharboe's avatar
oharboe committed
2124

2125
2126
2127
	return ERROR_OK;
}

2128
COMMAND_HANDLER(handle_halt_command)
2129
{
2130
	LOG_DEBUG("-");
2131

2132
	struct target *target = get_current_target(CMD_CTX);
2133
2134
	int retval = target_halt(target);
	if (ERROR_OK != retval)
2135
		return retval;
oharboe's avatar
oharboe committed
2136

2137
	if (CMD_ARGC == 1)
2138
	{
2139
		unsigned wait;
2140
		retval = parse_uint(CMD_ARGV[0], &wait);
2141
2142
2143
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		if (!wait)
2144
2145
2146
			return ERROR_OK;
	}

2147
	return CALL_COMMAND_HANDLER(handle_wait_halt_command);
2148
2149
}

2150
COMMAND_HANDLER(handle_soft_reset_halt_command)
2151
{
2152
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2153

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

oharboe's avatar
   
oharboe committed
2156
	target->type->soft_reset_halt(target);
oharboe's avatar
oharboe committed
2157

2158
2159
2160
	return ERROR_OK;
}

2161
COMMAND_HANDLER(handle_reset_command)
2162
{
2163
	if (CMD_ARGC > 1)
2164
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2165

2166
	enum target_reset_mode reset_mode = RESET_RUN;
2167
	if (CMD_ARGC == 1)
2168
	{
2169
		const Jim_Nvp *n;
2170
		n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
zwelch's avatar
zwelch committed
2171
		if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) {
oharboe's avatar
oharboe committed
2172
			return ERROR_COMMAND_SYNTAX_ERROR;
2173
		}
2174
		reset_mode = n->value;
2175
	}
oharboe's avatar
oharboe committed
2176

2177
	/* reset *all* targets */
2178
	return target_process_reset(CMD_CTX, reset_mode);
2179
2180
}

2181

2182
COMMAND_HANDLER(handle_resume_command)
2183
{
2184
	int current = 1;
2185
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2186
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2187

2188
	struct target *target = get_current_target(CMD_CTX);
zwelch's avatar
zwelch committed
2189
	target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
oharboe's avatar
oharboe committed
2190

2191
2192
	/* with no CMD_ARGV, resume from current pc, addr = 0,
	 * with one arguments, addr = CMD_ARGV[0],
zwelch's avatar
zwelch committed
2193
	 * handle breakpoints, not debugging */
2194
	uint32_t addr = 0;
2195
	if (CMD_ARGC == 1)
2196
	{
2197
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
2198
		current = 0;
2199
	}
oharboe's avatar
oharboe committed
2200

2201
	return target_resume(target, current, addr, 1, 0);
2202
2203
}

2204
COMMAND_HANDLER(handle_step_command)
2205
{
2206
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2207
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2208

2209
	LOG_DEBUG("-");
oharboe's avatar
oharboe committed
2210

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

2222
	struct target *target = get_current_target(CMD_CTX);
2223
2224

	return target->type->step(target, current_pc, addr, 1);
2225
2226
}

2227
static void handle_md_output(struct command_context *cmd_ctx,
Zachary T Welch's avatar
Zachary T Welch committed
2228
		struct target *target, uint32_t address, unsigned size,
2229
		unsigned count, const uint8_t *buffer)
2230
2231
2232
2233
2234
2235
2236
2237
2238
{
	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) {
2239
	case 4: value_fmt = "%8.8x "; break;
2240
	case 2: value_fmt = "%4.4x "; break;
2241
	case 1: value_fmt = "%2.2x "; break;
2242
	default:
2243
		/* "can't happen", caller checked */
2244
		LOG_ERROR("invalid memory read size: %u", size);
2245
		return;
2246
	}
2247

2248
2249
2250
2251
2252
2253
	for (unsigned i = 0; i < count; i++)
	{
		if (i % line_modulo == 0)
		{
			output_len += snprintf(output + output_len,
					sizeof(output) - output_len,
2254
					"0x%8.8x: ",
duane's avatar
duane committed
2255
					(unsigned)(address + (i*size)));
2256
		}
2257

zwelch's avatar
zwelch committed
2258
		uint32_t value = 0;
2259
		const uint8_t *value_ptr = buffer + i * size;
2260
2261
2262
2263
2264
2265
2266
2267
		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);
2268

2269
2270
2271
2272
2273
2274
2275
		if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
		{
			command_print(cmd_ctx, "%s", output);
			output_len = 0;
		}
	}
}
2276

2277
COMMAND_HANDLER(handle_md_command)
2278
{
2279
	if (CMD_ARGC < 1)
2280
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2281

2282
	unsigned size = 0;
2283
	switch (CMD_NAME[2]) {
2284
2285
2286
2287
	case 'w': size = 4; break;
	case 'h': size = 2; break;
	case 'b': size = 1; break;
	default: return ERROR_COMMAND_SYNTAX_ERROR;
2288
2289
	}

2290
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Zachary T Welch's avatar
Zachary T Welch committed
2291
	int (*fn)(struct target *target,
2292
2293
2294
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	if (physical)
	{
2295
		CMD_ARGC--;
2296
		CMD_ARGV++;
2297
2298
2299
2300
2301
		fn=target_read_phys_memory;
	} else
	{
		fn=target_read_memory;
	}
2302
	if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
2303
2304
2305
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2306

2307
	uint32_t address;
2308
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
oharboe's avatar
oharboe committed
2309

2310
	unsigned count = 1;
2311
	if (CMD_ARGC == 2)
2312
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
oharboe's avatar
oharboe committed
2313

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

2316
	struct target *target = get_current_target(CMD_CTX);
2317
	int retval = fn(target, address, size, count, buffer);
2318
	if (ERROR_OK == retval)
2319
		handle_md_output(CMD_CTX, target, address, size, count, buffer);
2320
2321

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

oharboe's avatar
oharboe committed
2323
	return retval;
2324
2325
}

Øyvind Harboe's avatar
Øyvind Harboe committed
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
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
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;
		}
		int retval = fn(target, address + x * data_size, data_size, current, target_buf);
		if (retval != ERROR_OK)
		{
			break;
		}
2387
2388
		/* avoid GDB timeouts */
		keep_alive();
Øyvind Harboe's avatar
Øyvind Harboe committed
2389
2390
2391
2392
2393
2394
2395
	}
	free(target_buf);

	return retval;
}


2396
COMMAND_HANDLER(handle_mw_command)
2397
{
2398
	if (CMD_ARGC < 2)
2399
2400
2401
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2402
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Øyvind Harboe's avatar
Øyvind Harboe committed
2403
	target_write_fn fn;
2404
2405
	if (physical)
	{
2406
		CMD_ARGC--;
2407
		CMD_ARGV++;
2408
2409
2410
		fn=target_write_phys_memory;
	} else
	{
Øyvind Harboe's avatar
Øyvind Harboe committed
2411
		fn = target_write_memory_fast;
2412
	}
2413
	if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
oharboe's avatar
oharboe committed
2414
		return ERROR_COMMAND_SYNTAX_ERROR;
2415

2416
	uint32_t address;
2417
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
2418

2419
	uint32_t value;
2420
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
2421
2422

	unsigned count = 1;
2423
	if (CMD_ARGC == 3)
2424
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
oharboe's avatar
oharboe committed
2425

2426
	struct target *target = get_current_target(CMD_CTX);
2427
	unsigned wordsize;
2428
	switch (CMD_NAME[2])
2429
2430
	{
		case 'w':
oharboe's avatar
oharboe committed
2431
			wordsize = 4;
2432
2433
			break;
		case 'h':
oharboe's avatar
oharboe committed
2434
			wordsize = 2;
2435
2436
			break;
		case 'b':
oharboe's avatar
oharboe committed
2437
			wordsize = 1;
2438
2439
			break;
		default:
oharboe's avatar
oharboe committed
2440
			return ERROR_COMMAND_SYNTAX_ERROR;
2441
2442
	}

Øyvind Harboe's avatar
Øyvind Harboe committed
2443
	return target_fill_mem(target, address, fn, wordsize, value, count);
2444
2445
}

2446
static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
2447
		uint32_t *min_address, uint32_t *max_address)
2448
{
2449
	if (CMD_ARGC < 1 || CMD_ARGC > 5)
2450
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2451

2452
2453
	/* a base address isn't always necessary,
	 * default to 0x0 (i.e. don't relocate) */
2454
	if (CMD_ARGC >= 2)
2455
	{
2456
		uint32_t addr;
2457
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2458
2459
		image->base_address = addr;
		image->base_address_set = 1;
2460
2461
	}
	else
2462
		image->base_address_set = 0;
oharboe's avatar
oharboe committed
2463

2464
	image->start_address_set = 0;
oharboe's avatar
oharboe committed
2465

2466
	if (CMD_ARGC >= 4)
2467
	{
2468
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
2469
	}
2470
	if (CMD_ARGC == 5)
2471
	{
2472
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
2473
		// use size (given) to find max (required)
2474
		*max_address += *min_address;
2475
	}
oharboe's avatar
oharboe committed
2476

2477
	if (*min_address > *max_address)
2478
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2479

2480
2481
2482
	return ERROR_OK;
}

2483
COMMAND_HANDLER(handle_load_image_command)
2484
{
2485
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2486
	size_t buf_cnt;
2487
2488
2489
	uint32_t image_size;
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
2490
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2491
	struct image image;
2492

2493
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
2494
2495
2496
2497
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;

2498
	struct target *target = get_current_target(CMD_CTX);
Zachary T Welch's avatar
Zachary T Welch committed
2499
2500
2501

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

2503
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
2504
2505
2506
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2507

2508
	image_size = 0x0;
2509
	retval = ERROR_OK;
2510
2511
2512
2513
2514
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2515
			command_print(CMD_CTX,
2516
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2517
						  (int)(image.sections[i].size));
2518
2519
			break;
		}
oharboe's avatar
oharboe committed
2520

2521
2522
2523
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2524
2525
			break;
		}
oharboe's avatar
oharboe committed
2526

zwelch's avatar
zwelch committed
2527
2528
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
oharboe's avatar
oharboe committed
2529

2530
		/* DANGER!!! beware of unsigned comparision here!!! */
oharboe's avatar
oharboe committed
2531

zwelch's avatar
zwelch committed
2532
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
2533
				(image.sections[i].base_address < max_address))
2534
		{
zwelch's avatar
zwelch committed
2535
			if (image.sections[i].base_address < min_address)
2536
2537
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
2538
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
2539
				length -= offset;
2540
			}
oharboe's avatar
oharboe committed
2541

zwelch's avatar
zwelch committed
2542
			if (image.sections[i].base_address + buf_cnt > max_address)
2543
			{
zwelch's avatar
zwelch committed
2544
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
2545
			}
oharboe's avatar
oharboe committed
2546

zwelch's avatar
zwelch committed
2547
			if ((retval = target_write_buffer(target, image.sections[i].base_address + offset, length, buffer + offset)) != ERROR_OK)
2548
2549
2550
2551
2552
			{
				free(buffer);
				break;
			}
			image_size += length;
2553
			command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
2554
						  (unsigned int)length,
zwelch's avatar
zwelch committed
2555
						  image.sections[i].base_address + offset);
2556
		}
oharboe's avatar
oharboe committed
2557

2558
2559
2560
		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
2561
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2562
	{
2563
		command_print(CMD_CTX, "downloaded %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
2564
2565
				"in %fs (%0.3f kb/s)", image_size,
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2566
2567
	}

2568
2569
	image_close(&image);

2570
	return retval;
2571
2572
2573

}

2574
COMMAND_HANDLER(handle_dump_image_command)
2575
{
Zachary T Welch's avatar
Zachary T Welch committed
2576
	struct fileio fileio;
oharboe's avatar
oharboe committed
2577

2578
	uint8_t buffer[560];
2579
	int retvaltemp;
oharboe's avatar
oharboe committed
2580
2581


2582
	struct target *target = get_current_target(CMD_CTX);
2583

2584
	if (CMD_ARGC != 3)
2585
	{
2586
		command_print(CMD_CTX, "usage: dump_image <filename> <address> <size>");
2587
2588
2589
		return ERROR_OK;
	}

2590
	uint32_t address;
2591
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address);
2592
	uint32_t size;
2593
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size);
2594

2595
	if (fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
2596
2597
2598
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2599

Zachary T Welch's avatar
Zachary T Welch committed
2600
2601
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2602

2603
	int retval = ERROR_OK;
2604
2605
	while (size > 0)
	{
Zachary T Welch's avatar
Zachary T Welch committed
2606
		size_t size_written;
2607
		uint32_t this_run_size = (size > 560) ? 560 : size;
2608
		retval = target_read_buffer(target, address, this_run_size, buffer);
2609
2610
2611
2612
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2613

2614
2615
2616
2617
2618
		retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2619

2620
2621
2622
2623
		size -= this_run_size;
		address += this_run_size;
	}

zwelch's avatar
zwelch committed
2624
	if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
2625
2626
		return retvaltemp;

Zachary T Welch's avatar
Zachary T Welch committed
2627
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2628
	{
2629
		command_print(CMD_CTX,
Freddie Chopin's avatar
Freddie Chopin committed
2630
				"dumped %ld bytes in %fs (%0.3f kb/s)", (long)fileio.size,
Zachary T Welch's avatar
Zachary T Welch committed
2631
				duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
2632
	}
oharboe's avatar
oharboe committed
2633

2634
	return retval;
2635
2636
}

2637
static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
2638
{
2639
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2640
	size_t buf_cnt;
2641
	uint32_t image_size;
2642
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2643
	int retval;
2644
2645
	uint32_t checksum = 0;
	uint32_t mem_checksum = 0;
2646

Zachary T Welch's avatar
Zachary T Welch committed
2647
	struct image image;
oharboe's avatar
oharboe committed
2648

2649
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2650

2651
	if (CMD_ARGC < 1)
2652
	{
2653
		return ERROR_COMMAND_SYNTAX_ERROR;
2654
	}
oharboe's avatar
oharboe committed
2655

2656
2657
	if (!target)
	{
2658
		LOG_ERROR("no target selected");
2659
		return ERROR_FAIL;
2660
	}
oharboe's avatar
oharboe committed
2661

Zachary T Welch's avatar
Zachary T Welch committed
2662
2663
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2664

2665
	if (CMD_ARGC >= 2)
2666
	{
2667
		uint32_t addr;
2668
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2669
		image.base_address = addr;
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
		image.base_address_set = 1;
	}
	else
	{
		image.base_address_set = 0;
		image.base_address = 0x0;
	}

	image.start_address_set = 0;

2680
	if ((retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL)) != ERROR_OK)
2681
	{
2682
		return retval;
2683
	}
oharboe's avatar
oharboe committed
2684

2685
	image_size = 0x0;
zwelch's avatar
zwelch committed
2686
	retval = ERROR_OK;
2687
2688
2689
2690
2691
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2692
			command_print(CMD_CTX,
2693
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2694
						  (int)(image.sections[i].size));
2695
2696
2697
2698
2699
			break;
		}
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2700
			break;
2701
		}
oharboe's avatar
oharboe committed
2702

oharboe's avatar
oharboe committed
2703
		if (verify)
2704
		{
oharboe's avatar
oharboe committed
2705
			/* calculate checksum of image */
2706
			image_calculate_checksum(buffer, buf_cnt, &checksum);
oharboe's avatar
oharboe committed
2707

oharboe's avatar
oharboe committed
2708
			retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
2709
			if (retval != ERROR_OK)
2710
			{
oharboe's avatar
oharboe committed
2711
2712
				free(buffer);
				break;
2713
			}
oharboe's avatar
oharboe committed
2714

2715
			if (checksum != mem_checksum)
2716
			{
oharboe's avatar
oharboe committed
2717
				/* failed crc checksum, fall back to a binary compare */
2718
				uint8_t *data;
oharboe's avatar
oharboe committed
2719

2720
				command_print(CMD_CTX, "checksum mismatch - attempting binary compare");
oharboe's avatar
oharboe committed
2721

2722
				data = (uint8_t*)malloc(buf_cnt);
oharboe's avatar
oharboe committed
2723
2724
2725
2726
2727

				/* Can we use 32bit word accesses? */
				int size = 1;
				int count = buf_cnt;
				if ((count % 4) == 0)
2728
				{
oharboe's avatar
oharboe committed
2729
2730
2731
					size *= 4;
					count /= 4;
				}
zwelch's avatar
zwelch committed
2732
				retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
oharboe's avatar
oharboe committed
2733
2734
				if (retval == ERROR_OK)
				{
2735
					uint32_t t;