target.c 124 KB
Newer Older
2001
		int retval = parse_uint(CMD_ARGV[0], &ms);
2002
		if (ERROR_OK != retval)
2003
		{
2004
			command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME);
2005
			return ERROR_COMMAND_SYNTAX_ERROR;
2006
		}
2007
2008
		// convert seconds (given) to milliseconds (needed)
		ms *= 1000;
2009
2010
	}

2011
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2012
	return target_wait_state(target, TARGET_HALTED, ms);
2013
2014
}

2015
2016
2017
2018
2019
2020
/* 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
2021
int target_wait_state(struct target *target, enum target_state state, int ms)
2022
2023
{
	int retval;
zwelch's avatar
zwelch committed
2024
2025
	long long then = 0, cur;
	int once = 1;
oharboe's avatar
oharboe committed
2026

2027
2028
	for (;;)
	{
zwelch's avatar
zwelch committed
2029
		if ((retval = target_poll(target)) != ERROR_OK)
2030
2031
2032
2033
2034
			return retval;
		if (target->state == state)
		{
			break;
		}
2035
		cur = timeval_ms();
2036
2037
		if (once)
		{
zwelch's avatar
zwelch committed
2038
			once = 0;
2039
			then = timeval_ms();
2040
			LOG_DEBUG("waiting for target %s...",
2041
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
2042
		}
oharboe's avatar
oharboe committed
2043

zwelch's avatar
zwelch committed
2044
		if (cur-then > 500)
2045
2046
2047
2048
		{
			keep_alive();
		}

zwelch's avatar
zwelch committed
2049
		if ((cur-then) > ms)
2050
		{
2051
			LOG_ERROR("timed out while waiting for target %s",
2052
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
oharboe's avatar
oharboe committed
2053
			return ERROR_FAIL;
2054
2055
		}
	}
oharboe's avatar
oharboe committed
2056

2057
2058
2059
	return ERROR_OK;
}

2060
COMMAND_HANDLER(handle_halt_command)
2061
{
2062
	LOG_DEBUG("-");
2063

2064
	struct target *target = get_current_target(CMD_CTX);
2065
2066
	int retval = target_halt(target);
	if (ERROR_OK != retval)
2067
		return retval;
oharboe's avatar
oharboe committed
2068

2069
	if (CMD_ARGC == 1)
2070
	{
2071
		unsigned wait;
2072
		retval = parse_uint(CMD_ARGV[0], &wait);
2073
2074
2075
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		if (!wait)
2076
2077
2078
			return ERROR_OK;
	}

2079
	return CALL_COMMAND_HANDLER(handle_wait_halt_command);
2080
2081
}

2082
COMMAND_HANDLER(handle_soft_reset_halt_command)
2083
{
2084
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2085

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

oharboe's avatar
   
oharboe committed
2088
	target->type->soft_reset_halt(target);
oharboe's avatar
oharboe committed
2089

2090
2091
2092
	return ERROR_OK;
}

2093
COMMAND_HANDLER(handle_reset_command)
2094
{
2095
	if (CMD_ARGC > 1)
2096
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2097

2098
	enum target_reset_mode reset_mode = RESET_RUN;
2099
	if (CMD_ARGC == 1)
2100
	{
2101
		const Jim_Nvp *n;
2102
		n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
zwelch's avatar
zwelch committed
2103
		if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) {
oharboe's avatar
oharboe committed
2104
			return ERROR_COMMAND_SYNTAX_ERROR;
2105
		}
2106
		reset_mode = n->value;
2107
	}
oharboe's avatar
oharboe committed
2108

2109
	/* reset *all* targets */
2110
	return target_process_reset(CMD_CTX, reset_mode);
2111
2112
}

2113

2114
COMMAND_HANDLER(handle_resume_command)
2115
{
2116
	int current = 1;
2117
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2118
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2119

2120
	struct target *target = get_current_target(CMD_CTX);
zwelch's avatar
zwelch committed
2121
	target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
oharboe's avatar
oharboe committed
2122

2123
2124
	/* with no CMD_ARGV, resume from current pc, addr = 0,
	 * with one arguments, addr = CMD_ARGV[0],
zwelch's avatar
zwelch committed
2125
	 * handle breakpoints, not debugging */
2126
	uint32_t addr = 0;
2127
	if (CMD_ARGC == 1)
2128
	{
2129
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
2130
		current = 0;
2131
	}
oharboe's avatar
oharboe committed
2132

2133
	return target_resume(target, current, addr, 1, 0);
2134
2135
}

2136
COMMAND_HANDLER(handle_step_command)
2137
{
2138
	if (CMD_ARGC > 1)
zwelch's avatar
zwelch committed
2139
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2140

2141
	LOG_DEBUG("-");
oharboe's avatar
oharboe committed
2142

2143
2144
	/* with no CMD_ARGV, step from current pc, addr = 0,
	 * with one argument addr = CMD_ARGV[0],
zwelch's avatar
zwelch committed
2145
	 * handle breakpoints, debugging */
2146
	uint32_t addr = 0;
2147
	int current_pc = 1;
2148
	if (CMD_ARGC == 1)
2149
	{
2150
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
2151
		current_pc = 0;
2152
	}
oharboe's avatar
oharboe committed
2153

2154
	struct target *target = get_current_target(CMD_CTX);
2155
2156

	return target->type->step(target, current_pc, addr, 1);
2157
2158
}

2159
static void handle_md_output(struct command_context *cmd_ctx,
Zachary T Welch's avatar
Zachary T Welch committed
2160
		struct target *target, uint32_t address, unsigned size,
2161
		unsigned count, const uint8_t *buffer)
2162
2163
2164
2165
2166
2167
2168
2169
2170
{
	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) {
2171
	case 4: value_fmt = "%8.8x "; break;
2172
	case 2: value_fmt = "%4.4x "; break;
2173
	case 1: value_fmt = "%2.2x "; break;
2174
	default:
2175
		/* "can't happen", caller checked */
2176
		LOG_ERROR("invalid memory read size: %u", size);
2177
		return;
2178
	}
2179

2180
2181
2182
2183
2184
2185
	for (unsigned i = 0; i < count; i++)
	{
		if (i % line_modulo == 0)
		{
			output_len += snprintf(output + output_len,
					sizeof(output) - output_len,
2186
					"0x%8.8x: ",
duane's avatar
duane committed
2187
					(unsigned)(address + (i*size)));
2188
		}
2189

zwelch's avatar
zwelch committed
2190
		uint32_t value = 0;
2191
		const uint8_t *value_ptr = buffer + i * size;
2192
2193
2194
2195
2196
2197
2198
2199
		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);
2200

2201
2202
2203
2204
2205
2206
2207
		if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
		{
			command_print(cmd_ctx, "%s", output);
			output_len = 0;
		}
	}
}
2208

2209
COMMAND_HANDLER(handle_md_command)
2210
{
2211
	if (CMD_ARGC < 1)
2212
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2213

2214
	unsigned size = 0;
2215
	switch (CMD_NAME[2]) {
2216
2217
2218
2219
	case 'w': size = 4; break;
	case 'h': size = 2; break;
	case 'b': size = 1; break;
	default: return ERROR_COMMAND_SYNTAX_ERROR;
2220
2221
	}

2222
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Zachary T Welch's avatar
Zachary T Welch committed
2223
	int (*fn)(struct target *target,
2224
2225
2226
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	if (physical)
	{
2227
		CMD_ARGC--;
2228
		CMD_ARGV++;
2229
2230
2231
2232
2233
		fn=target_read_phys_memory;
	} else
	{
		fn=target_read_memory;
	}
2234
	if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
2235
2236
2237
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2238

2239
	uint32_t address;
2240
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
oharboe's avatar
oharboe committed
2241

2242
	unsigned count = 1;
2243
	if (CMD_ARGC == 2)
2244
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
oharboe's avatar
oharboe committed
2245

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

2248
	struct target *target = get_current_target(CMD_CTX);
2249
	int retval = fn(target, address, size, count, buffer);
2250
	if (ERROR_OK == retval)
2251
		handle_md_output(CMD_CTX, target, address, size, count, buffer);
2252
2253

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

oharboe's avatar
oharboe committed
2255
	return retval;
2256
2257
}

2258
COMMAND_HANDLER(handle_mw_command)
2259
{
2260
	if (CMD_ARGC < 2)
2261
2262
2263
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
2264
	bool physical=strcmp(CMD_ARGV[0], "phys")==0;
Zachary T Welch's avatar
Zachary T Welch committed
2265
	int (*fn)(struct target *target,
2266
2267
2268
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	if (physical)
	{
2269
		CMD_ARGC--;
2270
		CMD_ARGV++;
2271
2272
2273
2274
2275
		fn=target_write_phys_memory;
	} else
	{
		fn=target_write_memory;
	}
2276
	if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
oharboe's avatar
oharboe committed
2277
		return ERROR_COMMAND_SYNTAX_ERROR;
2278

2279
	uint32_t address;
2280
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
2281

2282
	uint32_t value;
2283
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
2284
2285

	unsigned count = 1;
2286
	if (CMD_ARGC == 3)
2287
		COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
oharboe's avatar
oharboe committed
2288

2289
	struct target *target = get_current_target(CMD_CTX);
2290
	unsigned wordsize;
2291
	uint8_t value_buf[4];
2292
	switch (CMD_NAME[2])
2293
2294
	{
		case 'w':
oharboe's avatar
oharboe committed
2295
			wordsize = 4;
2296
2297
2298
			target_buffer_set_u32(target, value_buf, value);
			break;
		case 'h':
oharboe's avatar
oharboe committed
2299
			wordsize = 2;
2300
2301
2302
			target_buffer_set_u16(target, value_buf, value);
			break;
		case 'b':
oharboe's avatar
oharboe committed
2303
			wordsize = 1;
2304
2305
2306
			value_buf[0] = value;
			break;
		default:
oharboe's avatar
oharboe committed
2307
			return ERROR_COMMAND_SYNTAX_ERROR;
2308
	}
2309
	for (unsigned i = 0; i < count; i++)
2310
	{
2311
		int retval = fn(target,
2312
2313
				address + i * wordsize, wordsize, 1, value_buf);
		if (ERROR_OK != retval)
oharboe's avatar
oharboe committed
2314
			return retval;
2315
		keep_alive();
2316
2317
2318
2319
2320
2321
	}

	return ERROR_OK;

}

2322
static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
2323
		uint32_t *min_address, uint32_t *max_address)
2324
{
2325
	if (CMD_ARGC < 1 || CMD_ARGC > 5)
2326
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2327

2328
2329
	/* a base address isn't always necessary,
	 * default to 0x0 (i.e. don't relocate) */
2330
	if (CMD_ARGC >= 2)
2331
	{
2332
		uint32_t addr;
2333
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2334
2335
		image->base_address = addr;
		image->base_address_set = 1;
2336
2337
	}
	else
2338
		image->base_address_set = 0;
oharboe's avatar
oharboe committed
2339

2340
	image->start_address_set = 0;
oharboe's avatar
oharboe committed
2341

2342
	if (CMD_ARGC >= 4)
2343
	{
2344
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
2345
	}
2346
	if (CMD_ARGC == 5)
2347
	{
2348
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
2349
		// use size (given) to find max (required)
2350
		*max_address += *min_address;
2351
	}
oharboe's avatar
oharboe committed
2352

2353
	if (*min_address > *max_address)
2354
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2355

2356
2357
2358
	return ERROR_OK;
}

2359
COMMAND_HANDLER(handle_load_image_command)
2360
{
2361
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2362
	size_t buf_cnt;
2363
2364
2365
	uint32_t image_size;
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
2366
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2367
	struct image image;
2368

2369
	int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
2370
2371
2372
2373
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;

2374
	struct target *target = get_current_target(CMD_CTX);
Zachary T Welch's avatar
Zachary T Welch committed
2375
2376
2377

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

2379
	if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
2380
2381
2382
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2383

2384
	image_size = 0x0;
2385
	retval = ERROR_OK;
2386
2387
2388
2389
2390
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2391
			command_print(CMD_CTX,
2392
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2393
						  (int)(image.sections[i].size));
2394
2395
			break;
		}
oharboe's avatar
oharboe committed
2396

2397
2398
2399
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2400
2401
			break;
		}
oharboe's avatar
oharboe committed
2402

zwelch's avatar
zwelch committed
2403
2404
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
oharboe's avatar
oharboe committed
2405

2406
		/* DANGER!!! beware of unsigned comparision here!!! */
oharboe's avatar
oharboe committed
2407

zwelch's avatar
zwelch committed
2408
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
2409
				(image.sections[i].base_address < max_address))
2410
		{
zwelch's avatar
zwelch committed
2411
			if (image.sections[i].base_address < min_address)
2412
2413
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
2414
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
2415
				length -= offset;
2416
			}
oharboe's avatar
oharboe committed
2417

zwelch's avatar
zwelch committed
2418
			if (image.sections[i].base_address + buf_cnt > max_address)
2419
			{
zwelch's avatar
zwelch committed
2420
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
2421
			}
oharboe's avatar
oharboe committed
2422

zwelch's avatar
zwelch committed
2423
			if ((retval = target_write_buffer(target, image.sections[i].base_address + offset, length, buffer + offset)) != ERROR_OK)
2424
2425
2426
2427
2428
			{
				free(buffer);
				break;
			}
			image_size += length;
2429
			command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
2430
						  (unsigned int)length,
zwelch's avatar
zwelch committed
2431
						  image.sections[i].base_address + offset);
2432
		}
oharboe's avatar
oharboe committed
2433

2434
2435
2436
		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
2437
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2438
	{
2439
		command_print(CMD_CTX, "downloaded %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
2440
2441
				"in %fs (%0.3f kb/s)", image_size,
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2442
2443
	}

2444
2445
	image_close(&image);

2446
	return retval;
2447
2448
2449

}

2450
COMMAND_HANDLER(handle_dump_image_command)
2451
{
Zachary T Welch's avatar
Zachary T Welch committed
2452
	struct fileio fileio;
oharboe's avatar
oharboe committed
2453

2454
	uint8_t buffer[560];
2455
	int retvaltemp;
oharboe's avatar
oharboe committed
2456
2457


2458
	struct target *target = get_current_target(CMD_CTX);
2459

2460
	if (CMD_ARGC != 3)
2461
	{
2462
		command_print(CMD_CTX, "usage: dump_image <filename> <address> <size>");
2463
2464
2465
		return ERROR_OK;
	}

2466
	uint32_t address;
2467
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address);
2468
	uint32_t size;
2469
	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size);
2470

2471
	if (fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
2472
2473
2474
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2475

Zachary T Welch's avatar
Zachary T Welch committed
2476
2477
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2478

2479
	int retval = ERROR_OK;
2480
2481
	while (size > 0)
	{
Zachary T Welch's avatar
Zachary T Welch committed
2482
		size_t size_written;
2483
		uint32_t this_run_size = (size > 560) ? 560 : size;
2484
		retval = target_read_buffer(target, address, this_run_size, buffer);
2485
2486
2487
2488
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2489

2490
2491
2492
2493
2494
		retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2495

2496
2497
2498
2499
		size -= this_run_size;
		address += this_run_size;
	}

zwelch's avatar
zwelch committed
2500
	if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
2501
2502
		return retvaltemp;

Zachary T Welch's avatar
Zachary T Welch committed
2503
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2504
	{
2505
		command_print(CMD_CTX,
Freddie Chopin's avatar
Freddie Chopin committed
2506
				"dumped %ld bytes in %fs (%0.3f kb/s)", (long)fileio.size,
Zachary T Welch's avatar
Zachary T Welch committed
2507
				duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
2508
	}
oharboe's avatar
oharboe committed
2509

2510
	return retval;
2511
2512
}

2513
static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
2514
{
2515
	uint8_t *buffer;
Zachary T Welch's avatar
Zachary T Welch committed
2516
	size_t buf_cnt;
2517
	uint32_t image_size;
2518
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2519
	int retval;
2520
2521
	uint32_t checksum = 0;
	uint32_t mem_checksum = 0;
2522

Zachary T Welch's avatar
Zachary T Welch committed
2523
	struct image image;
oharboe's avatar
oharboe committed
2524

2525
	struct target *target = get_current_target(CMD_CTX);
oharboe's avatar
oharboe committed
2526

2527
	if (CMD_ARGC < 1)
2528
	{
2529
		return ERROR_COMMAND_SYNTAX_ERROR;
2530
	}
oharboe's avatar
oharboe committed
2531

2532
2533
	if (!target)
	{
2534
		LOG_ERROR("no target selected");
2535
		return ERROR_FAIL;
2536
	}
oharboe's avatar
oharboe committed
2537

Zachary T Welch's avatar
Zachary T Welch committed
2538
2539
	struct duration bench;
	duration_start(&bench);
oharboe's avatar
oharboe committed
2540

2541
	if (CMD_ARGC >= 2)
2542
	{
2543
		uint32_t addr;
2544
		COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
2545
		image.base_address = addr;
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
		image.base_address_set = 1;
	}
	else
	{
		image.base_address_set = 0;
		image.base_address = 0x0;
	}

	image.start_address_set = 0;

2556
	if ((retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL)) != ERROR_OK)
2557
	{
2558
		return retval;
2559
	}
oharboe's avatar
oharboe committed
2560

2561
	image_size = 0x0;
zwelch's avatar
zwelch committed
2562
	retval = ERROR_OK;
2563
2564
2565
2566
2567
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
2568
			command_print(CMD_CTX,
2569
						  "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
2570
						  (int)(image.sections[i].size));
2571
2572
2573
2574
2575
			break;
		}
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2576
			break;
2577
		}
oharboe's avatar
oharboe committed
2578

oharboe's avatar
oharboe committed
2579
		if (verify)
2580
		{
oharboe's avatar
oharboe committed
2581
			/* calculate checksum of image */
2582
			image_calculate_checksum(buffer, buf_cnt, &checksum);
oharboe's avatar
oharboe committed
2583

oharboe's avatar
oharboe committed
2584
			retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
2585
			if (retval != ERROR_OK)
2586
			{
oharboe's avatar
oharboe committed
2587
2588
				free(buffer);
				break;
2589
			}
oharboe's avatar
oharboe committed
2590

2591
			if (checksum != mem_checksum)
2592
			{
oharboe's avatar
oharboe committed
2593
				/* failed crc checksum, fall back to a binary compare */
2594
				uint8_t *data;
oharboe's avatar
oharboe committed
2595

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

2598
				data = (uint8_t*)malloc(buf_cnt);
oharboe's avatar
oharboe committed
2599
2600
2601
2602
2603

				/* Can we use 32bit word accesses? */
				int size = 1;
				int count = buf_cnt;
				if ((count % 4) == 0)
2604
				{
oharboe's avatar
oharboe committed
2605
2606
2607
					size *= 4;
					count /= 4;
				}
zwelch's avatar
zwelch committed
2608
				retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
oharboe's avatar
oharboe committed
2609
2610
				if (retval == ERROR_OK)
				{
2611
					uint32_t t;
oharboe's avatar
oharboe committed
2612
					for (t = 0; t < buf_cnt; t++)
oharboe's avatar
oharboe committed
2613
					{
oharboe's avatar
oharboe committed
2614
2615
						if (data[t] != buffer[t])
						{
2616
							command_print(CMD_CTX,
2617
2618
2619
										  "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
2620
										  buffer[t]);
oharboe's avatar
oharboe committed
2621
2622
							free(data);
							free(buffer);
zwelch's avatar
zwelch committed
2623
							retval = ERROR_FAIL;
oharboe's avatar
oharboe committed
2624
2625
							goto done;
						}
zwelch's avatar
zwelch committed
2626
						if ((t%16384) == 0)
oharboe's avatar
oharboe committed
2627
2628
2629
						{
							keep_alive();
						}
oharboe's avatar
oharboe committed
2630
					}
2631
				}
oharboe's avatar
oharboe committed
2632

oharboe's avatar
oharboe committed
2633
2634
2635
2636
				free(data);
			}
		} else
		{
2637
			command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx",
2638
						  image.sections[i].base_address,
duane's avatar
duane committed
2639
						  buf_cnt);
2640
		}
oharboe's avatar
oharboe committed
2641

2642
2643
2644
		free(buffer);
		image_size += buf_cnt;
	}
oharboe's avatar
oharboe committed
2645
done:
Zachary T Welch's avatar
Zachary T Welch committed
2646
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2647
	{
2648
		command_print(CMD_CTX, "verified %" PRIu32 " bytes "
Zachary T Welch's avatar
Zachary T Welch committed
2649
2650
				"in %fs (%0.3f kb/s)", image_size,
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2651
	}
oharboe's avatar
oharboe committed
2652

2653
	image_close(&image);
oharboe's avatar
oharboe committed
2654

2655
	return retval;
2656
2657
}

2658
COMMAND_HANDLER(handle_verify_image_command)
oharboe's avatar
oharboe committed
2659
{
2660
	return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1);
oharboe's avatar
oharboe committed
2661
2662
}

2663
COMMAND_HANDLER(handle_test_image_command)
oharboe's avatar
oharboe committed
2664
{
2665
	return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0);
oharboe's avatar
oharboe committed
2666
2667
}

2668
static int handle_bp_command_list(struct command_context *cmd_ctx)
2669
{
Zachary T Welch's avatar
Zachary T Welch committed
2670
	struct target *target = get_current_target(cmd_ctx);
2671
	struct breakpoint *breakpoint = target->breakpoints;
zwelch's avatar
zwelch committed
2672
	while (breakpoint)
2673
	{
zwelch's avatar
zwelch committed
2674
		if (breakpoint->type == BKPT_SOFT)
2675
		{
zwelch's avatar
zwelch committed
2676
2677
			char* buf = buf_to_str(breakpoint->orig_instr,
					breakpoint->length, 16);
duane's avatar
duane committed
2678
			command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
2679
					breakpoint->address,
duane's avatar
duane committed
2680
					breakpoint->length,
zwelch's avatar
zwelch committed
2681
2682
					breakpoint->set, buf);
			free(buf);
2683
2684
2685
		}
		else
		{
duane's avatar
duane committed
2686
			command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i",
2687
						  breakpoint->address,
duane's avatar
duane committed
2688
						  breakpoint->length, breakpoint->set);
2689
		}
zwelch's avatar
zwelch committed
2690
2691

		breakpoint = breakpoint->next;
2692
	}
zwelch's avatar
zwelch committed
2693
2694
2695
	return ERROR_OK;
}

2696
static int handle_bp_command_set(struct command_context *cmd_ctx,
zwelch's avatar