target.c 123 KB
Newer Older
oharboe's avatar
oharboe committed
2001

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

2004
2005
2006
	return ERROR_OK;
}

2007
COMMAND_HANDLER(handle_poll_command)
2008
{
2009
	int retval = ERROR_OK;
2010
	struct target *target = get_current_target(CMD_CTX);
2011

2012
	if (CMD_ARGC == 0)
2013
	{
2014
		command_print(CMD_CTX, "background polling: %s",
2015
				jtag_poll_get_enabled() ? "on" : "off");
2016
		command_print(CMD_CTX, "TAP: %s (%s)",
zwelch's avatar
zwelch committed
2017
2018
2019
2020
				target->tap->dotted_name,
				target->tap->enabled ? "enabled" : "disabled");
		if (!target->tap->enabled)
			return ERROR_OK;
2021
		if ((retval = target_poll(target)) != ERROR_OK)
2022
			return retval;
2023
		if ((retval = target_arch_state(target)) != ERROR_OK)
2024
			return retval;
2025
	}
2026
	else if (CMD_ARGC == 1)
2027
	{
2028
2029
2030
2031
2032
		bool enable;
		COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
		jtag_poll_set_enabled(enable);
	}
	else
2033
2034
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
2035
	}
oharboe's avatar
oharboe committed
2036

2037
	return retval;
2038
2039
}

2040
COMMAND_HANDLER(handle_wait_halt_command)
2041
{
2042
	if (CMD_ARGC > 1)
2043
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2044

2045
	unsigned ms = 5000;
2046
	if (1 == CMD_ARGC)
2047
	{
2048
		int retval = parse_uint(CMD_ARGV[0], &ms);
2049
		if (ERROR_OK != retval)
2050
		{
2051
			command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME);
2052
			return ERROR_COMMAND_SYNTAX_ERROR;
2053
		}
2054
2055
		// convert seconds (given) to milliseconds (needed)
		ms *= 1000;
2056
2057
	}

2058
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2059
	return target_wait_state(target, TARGET_HALTED, ms);
2060
2061
}

2062
2063
2064
2065
2066
2067
/* 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
2068
int target_wait_state(struct target *target, enum target_state state, int ms)
2069
2070
{
	int retval;
zwelch's avatar
zwelch committed
2071
2072
	long long then = 0, cur;
	int once = 1;
oharboe's avatar
oharboe committed
2073

2074
2075
	for (;;)
	{
zwelch's avatar
zwelch committed
2076
		if ((retval = target_poll(target)) != ERROR_OK)
2077
2078
2079
2080
2081
			return retval;
		if (target->state == state)
		{
			break;
		}
2082
		cur = timeval_ms();
2083
2084
		if (once)
		{
zwelch's avatar
zwelch committed
2085
			once = 0;
2086
			then = timeval_ms();
2087
			LOG_DEBUG("waiting for target %s...",
2088
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
2089
		}
oharboe's avatar
oharboe committed
2090

zwelch's avatar
zwelch committed
2091
		if (cur-then > 500)
2092
2093
2094
2095
		{
			keep_alive();
		}

zwelch's avatar
zwelch committed
2096
		if ((cur-then) > ms)
2097
		{
2098
			LOG_ERROR("timed out while waiting for target %s",
2099
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
oharboe's avatar
oharboe committed
2100
			return ERROR_FAIL;
2101
2102
		}
	}
oharboe's avatar
oharboe committed
2103

2104
2105
2106
	return ERROR_OK;
}

2107
COMMAND_HANDLER(handle_halt_command)
2108
{
2109
	LOG_DEBUG("-");
2110

2111
	struct target *target = get_current_target(CMD_CTX);
2112
2113
	int retval = target_halt(target);
	if (ERROR_OK != retval)
2114
		return retval;
oharboe's avatar
oharboe committed
2115

2116
	if (CMD_ARGC == 1)
2117
	{
2118
		unsigned wait;
2119
		retval = parse_uint(CMD_ARGV[0], &wait);
2120
2121
2122
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		if (!wait)
2123
2124
2125
			return ERROR_OK;
	}

2126
	return CALL_COMMAND_HANDLER(handle_wait_halt_command);
2127
2128
}

2129
COMMAND_HANDLER(handle_soft_reset_halt_command)
2130
{
2131
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2132

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

oharboe's avatar
   
oharboe committed
2135
	target->type->soft_reset_halt(target);
oharboe's avatar
oharboe committed
2136

2137
2138
2139
	return ERROR_OK;
}

2140
COMMAND_HANDLER(handle_reset_command)
2141
{
2142
	if (CMD_ARGC > 1)
2143
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2144

2145
	enum target_reset_mode reset_mode = RESET_RUN;
2146
	if (CMD_ARGC == 1)
2147
	{
2148
		const Jim_Nvp *n;
2149
		n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
zwelch's avatar
zwelch committed
2150
		if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) {
oharboe's avatar
oharboe committed
2151
			return ERROR_COMMAND_SYNTAX_ERROR;
2152
		}
2153
		reset_mode = n->value;
2154
	}
oharboe's avatar
oharboe committed
2155

2156
	/* reset *all* targets */
2157
	return target_process_reset(CMD_CTX, reset_mode);
2158
2159
}

2160

2161
COMMAND_HANDLER(handle_resume_command)
2162
{
2163
	int current = 1;
2164
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2165
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2166

2167
	struct target *target = get_current_target(CMD_CTX);
zwelch's avatar
zwelch committed
2168
	target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
oharboe's avatar
oharboe committed
2169

2170
2171
	/* with no CMD_ARGV, resume from current pc, addr = 0,
	 * with one arguments, addr = CMD_ARGV[0],
zwelch's avatar
zwelch committed
2172
	 * handle breakpoints, not debugging */
2173
	uint32_t addr = 0;
2174
	if (CMD_ARGC == 1)
2175
	{
2176
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
2177
		current = 0;
2178
	}
oharboe's avatar
oharboe committed
2179

2180
	return target_resume(target, current, addr, 1, 0);
2181
2182
}

2183
COMMAND_HANDLER(handle_step_command)
2184
{
2185
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2186
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2187

2188
	LOG_DEBUG("-");
oharboe's avatar
oharboe committed
2189

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

2201
	struct target *target = get_current_target(CMD_CTX);
2202
2203

	return target->type->step(target, current_pc, addr, 1);
2204
2205
}

2206
static void handle_md_output(struct command_context *cmd_ctx,
Zachary T Welch's avatar
Zachary T Welch committed
2207
		struct target *target, uint32_t address, unsigned size,
2208
		unsigned count, const uint8_t *buffer)
2209
2210
2211
2212
2213
2214
2215
2216
2217
{
	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) {
2218
2219
2220
	case 4: value_fmt = "%8.8x "; break;
	case 2: value_fmt = "%4.2x "; break;
	case 1: value_fmt = "%2.2x "; break;
2221
2222
2223
2224
	default:
		LOG_ERROR("invalid memory read size: %u", size);
		exit(-1);
	}
2225

2226
2227
2228
2229
2230
2231
	for (unsigned i = 0; i < count; i++)
	{
		if (i % line_modulo == 0)
		{
			output_len += snprintf(output + output_len,
					sizeof(output) - output_len,
2232
					"0x%8.8x: ",
duane's avatar
duane committed
2233
					(unsigned)(address + (i*size)));
2234
		}
2235

zwelch's avatar
zwelch committed
2236
		uint32_t value = 0;
2237
		const uint8_t *value_ptr = buffer + i * size;
2238
2239
2240
2241
2242
2243
2244
2245
		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);
2246

2247
2248
2249
2250
2251
2252
2253
		if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
		{
			command_print(cmd_ctx, "%s", output);
			output_len = 0;
		}
	}
}
2254

2255
COMMAND_HANDLER(handle_md_command)
2256
{
2257
	if (CMD_ARGC < 1)
2258
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2259

2260
	unsigned size = 0;
2261
	switch (CMD_NAME[2]) {
2262
2263
2264
2265
	case 'w': size = 4; break;
	case 'h': size = 2; break;
	case 'b': size = 1; break;
	default: return ERROR_COMMAND_SYNTAX_ERROR;
2266
2267
	}

2268
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Zachary T Welch's avatar
Zachary T Welch committed
2269
	int (*fn)(struct target *target,
2270
2271
2272
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	if (physical)
	{
2273
		CMD_ARGC--;
2274
		CMD_ARGV++;
2275
2276
2277
2278
2279
		fn=target_read_phys_memory;
	} else
	{
		fn=target_read_memory;
	}
2280
	if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
2281
2282
2283
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2284

2285
	uint32_t address;
2286
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
oharboe's avatar
oharboe committed
2287

2288
	unsigned count = 1;
2289
	if (CMD_ARGC == 2)
2290
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
oharboe's avatar
oharboe committed
2291

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

2294
	struct target *target = get_current_target(CMD_CTX);
2295
	int retval = fn(target, address, size, count, buffer);
2296
	if (ERROR_OK == retval)
2297
		handle_md_output(CMD_CTX, target, address, size, count, buffer);
2298
2299

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

oharboe's avatar
oharboe committed
2301
	return retval;
2302
2303
}

2304
COMMAND_HANDLER(handle_mw_command)
2305
{
2306
	if (CMD_ARGC < 2)
2307
2308
2309
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
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_write_phys_memory;
	} else
	{
		fn=target_write_memory;
	}
2322
	if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
oharboe's avatar
oharboe committed
2323
		return ERROR_COMMAND_SYNTAX_ERROR;
2324

2325
	uint32_t address;
2326
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
2327

2328
	uint32_t value;
2329
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
2330
2331

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

2335
	struct target *target = get_current_target(CMD_CTX);
2336
	unsigned wordsize;
2337
	uint8_t value_buf[4];
2338
	switch (CMD_NAME[2])
2339
2340
	{
		case 'w':
oharboe's avatar
oharboe committed
2341
			wordsize = 4;
2342
2343
2344
			target_buffer_set_u32(target, value_buf, value);
			break;
		case 'h':
oharboe's avatar
oharboe committed
2345
			wordsize = 2;
2346
2347
2348
			target_buffer_set_u16(target, value_buf, value);
			break;
		case 'b':
oharboe's avatar
oharboe committed
2349
			wordsize = 1;
2350
2351
2352
			value_buf[0] = value;
			break;
		default:
oharboe's avatar
oharboe committed
2353
			return ERROR_COMMAND_SYNTAX_ERROR;
2354
	}
2355
	for (unsigned i = 0; i < count; i++)
2356
	{
2357
		int retval = fn(target,
2358
2359
				address + i * wordsize, wordsize, 1, value_buf);
		if (ERROR_OK != retval)
oharboe's avatar
oharboe committed
2360
			return retval;
2361
		keep_alive();
2362
2363
2364
2365
2366
2367
	}

	return ERROR_OK;

}

2368
static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
2369
		uint32_t *min_address, uint32_t *max_address)
2370
{
2371
	if (CMD_ARGC < 1 || CMD_ARGC > 5)
2372
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2373

2374
2375
	/* a base address isn't always necessary,
	 * default to 0x0 (i.e. don't relocate) */
2376
	if (CMD_ARGC >= 2)
2377
	{
2378
		uint32_t addr;
2379
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2380
2381
		image->base_address = addr;
		image->base_address_set = 1;
2382
2383
	}
	else
2384
		image->base_address_set = 0;
oharboe's avatar
oharboe committed
2385

2386
	image->start_address_set = 0;
oharboe's avatar
oharboe committed
2387

2388
	if (CMD_ARGC >= 4)
2389
	{
2390
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
2391
	}
2392
	if (CMD_ARGC == 5)
2393
	{
2394
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
2395
		// use size (given) to find max (required)
2396
		*max_address += *min_address;
2397
	}
oharboe's avatar
oharboe committed
2398

2399
	if (*min_address > *max_address)
2400
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2401

2402
2403
2404
	return ERROR_OK;
}

2405
COMMAND_HANDLER(handle_load_image_command)
2406
{
2407
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2408
	size_t buf_cnt;
2409
2410
2411
	uint32_t image_size;
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
2412
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2413
	struct image image;
2414

2415
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
2416
2417
2418
2419
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;

2420
	struct target *target = get_current_target(CMD_CTX);
Zachary T Welch's avatar
Zachary T Welch committed
2421
2422
2423

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

2425
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
2426
2427
2428
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2429

2430
	image_size = 0x0;
2431
	retval = ERROR_OK;
2432
2433
2434
2435
2436
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2437
			command_print(CMD_CTX,
2438
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2439
						  (int)(image.sections[i].size));
2440
2441
			break;
		}
oharboe's avatar
oharboe committed
2442

2443
2444
2445
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2446
2447
			break;
		}
oharboe's avatar
oharboe committed
2448

zwelch's avatar
zwelch committed
2449
2450
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
oharboe's avatar
oharboe committed
2451

2452
		/* DANGER!!! beware of unsigned comparision here!!! */
oharboe's avatar
oharboe committed
2453

zwelch's avatar
zwelch committed
2454
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
2455
				(image.sections[i].base_address < max_address))
2456
		{
zwelch's avatar
zwelch committed
2457
			if (image.sections[i].base_address < min_address)
2458
2459
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
2460
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
2461
				length -= offset;
2462
			}
oharboe's avatar
oharboe committed
2463

zwelch's avatar
zwelch committed
2464
			if (image.sections[i].base_address + buf_cnt > max_address)
2465
			{
zwelch's avatar
zwelch committed
2466
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
2467
			}
oharboe's avatar
oharboe committed
2468

zwelch's avatar
zwelch committed
2469
			if ((retval = target_write_buffer(target, image.sections[i].base_address + offset, length, buffer + offset)) != ERROR_OK)
2470
2471
2472
2473
2474
			{
				free(buffer);
				break;
			}
			image_size += length;
2475
			command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
2476
						  (unsigned int)length,
zwelch's avatar
zwelch committed
2477
						  image.sections[i].base_address + offset);
2478
		}
oharboe's avatar
oharboe committed
2479

2480
2481
2482
		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
2483
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2484
	{
2485
		command_print(CMD_CTX, "downloaded %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
2486
2487
				"in %fs (%0.3f kb/s)", image_size,
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2488
2489
	}

2490
2491
	image_close(&image);

2492
	return retval;
2493
2494
2495

}

2496
COMMAND_HANDLER(handle_dump_image_command)
2497
{
Zachary T Welch's avatar
Zachary T Welch committed
2498
	struct fileio fileio;
oharboe's avatar
oharboe committed
2499

2500
	uint8_t buffer[560];
2501
	int retvaltemp;
oharboe's avatar
oharboe committed
2502
2503


2504
	struct target *target = get_current_target(CMD_CTX);
2505

2506
	if (CMD_ARGC != 3)
2507
	{
2508
		command_print(CMD_CTX, "usage: dump_image <filename> <address> <size>");
2509
2510
2511
		return ERROR_OK;
	}

2512
	uint32_t address;
2513
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address);
2514
	uint32_t size;
2515
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size);
2516

2517
	if (fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
2518
2519
2520
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2521

Zachary T Welch's avatar
Zachary T Welch committed
2522
2523
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2524

2525
	int retval = ERROR_OK;
2526
2527
	while (size > 0)
	{
Zachary T Welch's avatar
Zachary T Welch committed
2528
		size_t size_written;
2529
		uint32_t this_run_size = (size > 560) ? 560 : size;
2530
		retval = target_read_buffer(target, address, this_run_size, buffer);
2531
2532
2533
2534
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2535

2536
2537
2538
2539
2540
		retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2541

2542
2543
2544
2545
		size -= this_run_size;
		address += this_run_size;
	}

zwelch's avatar
zwelch committed
2546
	if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
2547
2548
		return retvaltemp;

Zachary T Welch's avatar
Zachary T Welch committed
2549
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2550
	{
2551
		command_print(CMD_CTX,
2552
				"dumped %zu bytes in %fs (%0.3f kb/s)", fileio.size,
Zachary T Welch's avatar
Zachary T Welch committed
2553
				duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
2554
	}
oharboe's avatar
oharboe committed
2555

2556
	return retval;
2557
2558
}

2559
static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
2560
{
2561
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2562
	size_t buf_cnt;
2563
	uint32_t image_size;
2564
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2565
	int retval;
2566
2567
	uint32_t checksum = 0;
	uint32_t mem_checksum = 0;
2568

Zachary T Welch's avatar
Zachary T Welch committed
2569
	struct image image;
oharboe's avatar
oharboe committed
2570

2571
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2572

2573
	if (CMD_ARGC < 1)
2574
	{
2575
		return ERROR_COMMAND_SYNTAX_ERROR;
2576
	}
oharboe's avatar
oharboe committed
2577

2578
2579
	if (!target)
	{
2580
		LOG_ERROR("no target selected");
2581
		return ERROR_FAIL;
2582
	}
oharboe's avatar
oharboe committed
2583

Zachary T Welch's avatar
Zachary T Welch committed
2584
2585
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2586

2587
	if (CMD_ARGC >= 2)
2588
	{
2589
		uint32_t addr;
2590
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2591
		image.base_address = addr;
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
		image.base_address_set = 1;
	}
	else
	{
		image.base_address_set = 0;
		image.base_address = 0x0;
	}

	image.start_address_set = 0;

2602
	if ((retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL)) != ERROR_OK)
2603
	{
2604
		return retval;
2605
	}
oharboe's avatar
oharboe committed
2606

2607
	image_size = 0x0;
zwelch's avatar
zwelch committed
2608
	retval = ERROR_OK;
2609
2610
2611
2612
2613
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2614
			command_print(CMD_CTX,
2615
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2616
						  (int)(image.sections[i].size));
2617
2618
2619
2620
2621
			break;
		}
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2622
			break;
2623
		}
oharboe's avatar
oharboe committed
2624

oharboe's avatar
oharboe committed
2625
		if (verify)
2626
		{
oharboe's avatar
oharboe committed
2627
			/* calculate checksum of image */
2628
			image_calculate_checksum(buffer, buf_cnt, &checksum);
oharboe's avatar
oharboe committed
2629

oharboe's avatar
oharboe committed
2630
			retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
2631
			if (retval != ERROR_OK)
2632
			{
oharboe's avatar
oharboe committed
2633
2634
				free(buffer);
				break;
2635
			}
oharboe's avatar
oharboe committed
2636

2637
			if (checksum != mem_checksum)
2638
			{
oharboe's avatar
oharboe committed
2639
				/* failed crc checksum, fall back to a binary compare */
2640
				uint8_t *data;
oharboe's avatar
oharboe committed
2641

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

2644
				data = (uint8_t*)malloc(buf_cnt);
oharboe's avatar
oharboe committed
2645
2646
2647
2648
2649

				/* Can we use 32bit word accesses? */
				int size = 1;
				int count = buf_cnt;
				if ((count % 4) == 0)
2650
				{
oharboe's avatar
oharboe committed
2651
2652
2653
					size *= 4;
					count /= 4;
				}
zwelch's avatar
zwelch committed
2654
				retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
oharboe's avatar
oharboe committed
2655
2656
				if (retval == ERROR_OK)
				{
2657
					uint32_t t;
oharboe's avatar
oharboe committed
2658
					for (t = 0; t < buf_cnt; t++)
oharboe's avatar
oharboe committed
2659
					{
oharboe's avatar
oharboe committed
2660
2661
						if (data[t] != buffer[t])
						{
2662
							command_print(CMD_CTX,
2663
2664
2665
										  "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n",
										  (unsigned)(t + image.sections[i].base_address),
										  data[t],
duane's avatar
duane committed
2666
										  buffer[t]);
oharboe's avatar
oharboe committed
2667
2668
							free(data);
							free(buffer);
zwelch's avatar
zwelch committed
2669
							retval = ERROR_FAIL;
oharboe's avatar
oharboe committed
2670
2671
							goto done;
						}
zwelch's avatar
zwelch committed
2672
						if ((t%16384) == 0)
oharboe's avatar
oharboe committed
2673
2674
2675
						{
							keep_alive();
						}
oharboe's avatar
oharboe committed
2676
					}
2677
				}
oharboe's avatar
oharboe committed
2678

oharboe's avatar
oharboe committed
2679
2680
2681
2682
				free(data);
			}
		} else
		{
2683
			command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx",
2684
						  image.sections[i].base_address,
duane's avatar
duane committed
2685
						  buf_cnt);
2686
		}
oharboe's avatar
oharboe committed
2687

2688
2689
2690
		free(buffer);
		image_size += buf_cnt;
	}
oharboe's avatar
oharboe committed
2691
done:
Zachary T Welch's avatar
Zachary T Welch committed
2692
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2693
	{
2694
		command_print(CMD_CTX, "verified %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
2695
2696
				"in %fs (%0.3f kb/s)", image_size,
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2697
	}
oharboe's avatar
oharboe committed
2698

2699
	image_close(&image);
oharboe's avatar
oharboe committed
2700