target.c 118 KB
Newer Older
2001
2002
	if (argc == 0)
	{
2003
		command_print(cmd_ctx, "background polling: %s",
2004
				jtag_poll_get_enabled() ? "on" : "off");
zwelch's avatar
zwelch committed
2005
2006
2007
2008
2009
		command_print(cmd_ctx, "TAP: %s (%s)",
				target->tap->dotted_name,
				target->tap->enabled ? "enabled" : "disabled");
		if (!target->tap->enabled)
			return ERROR_OK;
2010
		if ((retval = target_poll(target)) != ERROR_OK)
2011
			return retval;
2012
		if ((retval = target_arch_state(target)) != ERROR_OK)
2013
2014
			return retval;

2015
	}
zwelch's avatar
zwelch committed
2016
	else if (argc == 1)
2017
2018
2019
	{
		if (strcmp(args[0], "on") == 0)
		{
2020
			jtag_poll_set_enabled(true);
2021
2022
2023
		}
		else if (strcmp(args[0], "off") == 0)
		{
2024
			jtag_poll_set_enabled(false);
2025
2026
2027
2028
2029
		}
		else
		{
			command_print(cmd_ctx, "arg is \"on\" or \"off\"");
		}
2030
2031
2032
	} else
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
2033
	}
oharboe's avatar
oharboe committed
2034

2035
	return retval;
2036
2037
}

2038
COMMAND_HANDLER(handle_wait_halt_command)
2039
{
2040
2041
	if (argc > 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2042

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

Zachary T Welch's avatar
Zachary T Welch committed
2056
	struct target *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2057
	return target_wait_state(target, TARGET_HALTED, ms);
2058
2059
}

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

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

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

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

2102
2103
2104
	return ERROR_OK;
}

2105
COMMAND_HANDLER(handle_halt_command)
2106
{
2107
	LOG_DEBUG("-");
2108

Zachary T Welch's avatar
Zachary T Welch committed
2109
	struct target *target = get_current_target(cmd_ctx);
2110
2111
	int retval = target_halt(target);
	if (ERROR_OK != retval)
2112
		return retval;
oharboe's avatar
oharboe committed
2113

2114
2115
	if (argc == 1)
	{
2116
2117
2118
2119
2120
		unsigned wait;
		retval = parse_uint(args[0], &wait);
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		if (!wait)
2121
2122
2123
			return ERROR_OK;
	}

2124
	return CALL_COMMAND_HANDLER(handle_wait_halt_command);
2125
2126
}

2127
COMMAND_HANDLER(handle_soft_reset_halt_command)
2128
{
Zachary T Welch's avatar
Zachary T Welch committed
2129
	struct target *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2130

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

oharboe's avatar
   
oharboe committed
2133
	target->type->soft_reset_halt(target);
oharboe's avatar
oharboe committed
2134

2135
2136
2137
	return ERROR_OK;
}

2138
COMMAND_HANDLER(handle_reset_command)
2139
{
2140
2141
	if (argc > 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2142

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

2154
	/* reset *all* targets */
2155
	return target_process_reset(cmd_ctx, reset_mode);
2156
2157
}

2158

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

Zachary T Welch's avatar
Zachary T Welch committed
2165
	struct target *target = get_current_target(cmd_ctx);
zwelch's avatar
zwelch committed
2166
	target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
oharboe's avatar
oharboe committed
2167

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

2178
	return target_resume(target, current, addr, 1, 0);
2179
2180
}

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

2186
	LOG_DEBUG("-");
oharboe's avatar
oharboe committed
2187

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

Zachary T Welch's avatar
Zachary T Welch committed
2199
	struct target *target = get_current_target(cmd_ctx);
2200
2201

	return target->type->step(target, current_pc, addr, 1);
2202
2203
}

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

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

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

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

2253
COMMAND_HANDLER(handle_md_command)
2254
{
2255
	if (argc < 1)
2256
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2257

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

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

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

2287
2288
	unsigned count = 1;
	if (argc == 2)
2289
		COMMAND_PARSE_NUMBER(uint, args[1], count);
oharboe's avatar
oharboe committed
2290

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

Zachary T Welch's avatar
Zachary T Welch committed
2293
	struct target *target = get_current_target(cmd_ctx);
2294
	int retval = fn(target, address, size, count, buffer);
2295
2296
	if (ERROR_OK == retval)
		handle_md_output(cmd_ctx, target, address, size, count, buffer);
2297
2298

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

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

2303
COMMAND_HANDLER(handle_mw_command)
2304
{
2305
2306
2307
2308
2309
	if (argc < 2)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
	bool physical=strcmp(args[0], "phys")==0;
Zachary T Welch's avatar
Zachary T Welch committed
2310
	int (*fn)(struct target *target,
2311
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
2312
	const char *cmd_name = CMD_NAME;
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
	if (physical)
	{
		argc--;
		args++;
		fn=target_write_phys_memory;
	} else
	{
		fn=target_write_memory;
	}
	if ((argc < 2) || (argc > 3))
oharboe's avatar
oharboe committed
2323
		return ERROR_COMMAND_SYNTAX_ERROR;
2324

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

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

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

Zachary T Welch's avatar
Zachary T Welch committed
2335
	struct target *target = get_current_target(cmd_ctx);
2336
	unsigned wordsize;
2337
	uint8_t value_buf[4];
2338
	switch (cmd_name[6])
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;

}

Zachary T Welch's avatar
Zachary T Welch committed
2368
static COMMAND_HELPER(parse_load_image_command_args, struct image *image,
2369
		uint32_t *min_address, uint32_t *max_address)
2370
{
2371
	if (argc < 1 || 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
2377
	if (argc >= 2)
	{
2378
		uint32_t addr;
2379
		COMMAND_PARSE_NUMBER(u32, args[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 (argc >= 4)
2389
	{
2390
		COMMAND_PARSE_NUMBER(u32, args[3], *min_address);
2391
	}
2392
	if (argc == 5)
2393
	{
2394
		COMMAND_PARSE_NUMBER(u32, args[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;
2408
2409
2410
2411
	uint32_t buf_cnt;
	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_args,
2416
2417
2418
2419
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;

Zachary T Welch's avatar
Zachary T Welch committed
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
2426
2427
2428
	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
	{
		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
2438
			command_print(cmd_ctx,
						  "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;
oharboe's avatar
oharboe committed
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
	{
Zachary T Welch's avatar
Zachary T Welch committed
2485
2486
2487
		command_print(cmd_ctx, "downloaded %" PRIu32 " bytes "
				"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


Zachary T Welch's avatar
Zachary T Welch committed
2504
	struct target *target = get_current_target(cmd_ctx);
2505
2506
2507
2508
2509
2510
2511

	if (argc != 3)
	{
		command_print(cmd_ctx, "usage: dump_image <filename> <address> <size>");
		return ERROR_OK;
	}

2512
	uint32_t address;
2513
	COMMAND_PARSE_NUMBER(u32, args[1], address);
2514
	uint32_t size;
2515
	COMMAND_PARSE_NUMBER(u32, args[2], size);
2516
2517
2518
2519
2520

	if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
	{
		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)
	{
2528
2529
		uint32_t size_written;
		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
	{
Zachary T Welch's avatar
Zachary T Welch committed
2551
2552
2553
		command_print(cmd_ctx,
				"dumped %lld bytes in %fs (%0.3f kb/s)", fileio.size,
				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;
2562
2563
	uint32_t buf_cnt;
	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

Zachary T Welch's avatar
Zachary T Welch committed
2571
	struct target *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2572

2573
2574
	if (argc < 1)
	{
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
2588
	if (argc >= 2)
	{
2589
		uint32_t addr;
2590
		COMMAND_PARSE_NUMBER(u32, args[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;

zwelch's avatar
zwelch committed
2602
	if ((retval = image_open(&image, args[0], (argc == 3) ? args[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
2615
			command_print(cmd_ctx,
						  "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
2643

				command_print(cmd_ctx, "checksum mismatch - attempting binary compare");

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
2663
2664
2665
							command_print(cmd_ctx,
										  "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
2684
			command_print(cmd_ctx, "address 0x%08" PRIx32 " length 0x%08" PRIx32 "",
						  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
	{
Zachary T Welch's avatar
Zachary T Welch committed
2694
2695
2696
		command_print(cmd_ctx, "verified %" PRIu32 " bytes "
				"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

2701
	return retval;
2702
2703
}

2704
COMMAND_HANDLER(handle_verify_image_command)
oharboe's avatar
oharboe committed
2705
{
2706
	return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1);
oharboe's avatar
oharboe committed
2707
2708
}

2709
COMMAND_HANDLER(handle_test_image_command)
oharboe's avatar
oharboe committed
2710
{
2711
	return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0);
oharboe's avatar
oharboe committed
2712
2713
}

2714
static int handle_bp_command_list(struct command_context *cmd_ctx)
2715
{
Zachary T Welch's avatar
Zachary T Welch committed
2716
	struct target *target = get_current_target(cmd_ctx);
2717
	struct breakpoint *breakpoint = target->breakpoints;
zwelch's avatar
zwelch committed
2718
	while (breakpoint)
2719
	{
zwelch's avatar
zwelch committed
2720
		if (breakpoint->type == BKPT_SOFT)
2721
		{
zwelch's avatar
zwelch committed
2722
2723
			char* buf = buf_to_str(breakpoint->orig_instr,
					breakpoint->length, 16);
duane's avatar
duane committed
2724
			command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
2725
					breakpoint->address,
duane's avatar
duane committed
2726
					breakpoint->length,
zwelch's avatar
zwelch committed
2727
2728
					breakpoint->set, buf);
			free(buf);
2729
2730
2731
		}
		else
		{
duane's avatar
duane committed
2732
			command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i",
2733
						  breakpoint->address,
duane's avatar
duane committed
2734
						  breakpoint->length, breakpoint->set);
2735
		}
zwelch's avatar
zwelch committed
2736
2737

		breakpoint = breakpoint->next;
2738
	}
zwelch's avatar
zwelch committed
2739
2740
2741
	return ERROR_OK;
}

2742
static int handle_bp_command_set(struct command_context *cmd_ctx,
2743
		uint32_t addr, uint32_t length, int hw)
zwelch's avatar
zwelch committed
2744
{
Zachary T Welch's avatar
Zachary T Welch committed
2745
	struct target *target = get_current_target(cmd_ctx);
zwelch's avatar
zwelch committed
2746
2747
	int retval = breakpoint_add(target, addr, length, hw);
	if (ERROR_OK == retval)
duane's avatar
duane committed
2748
		command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
2749
	else
zwelch's avatar
zwelch committed
2750
2751
2752
2753
		LOG_ERROR("Failure setting breakpoint");
	return retval;
}

2754
COMMAND_HANDLER(handle_bp_command)
zwelch's avatar
zwelch committed
2755
2756
2757
2758
2759
{
	if (argc == 0)
		return handle_bp_command_list(cmd_ctx);

	if (argc < 2 || argc > 3)
2760
2761
	{
		command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
zwelch's avatar