target.c 121 KB
Newer Older
2001
2002
					free(value);
				} else {
2003
					command_print(cmd_ctx, "(%i) %s (/%" PRIu32 ")",
2004
2005
2006
							  count, reg->name,
							  reg->size) ;
				}
2007
2008
2009
			}
			cache = cache->next;
		}
oharboe's avatar
oharboe committed
2010

2011
2012
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2013

2014
2015
2016
	/* access a single register by its ordinal number */
	if ((args[0][0] >= '0') && (args[0][0] <= '9'))
	{
2017
		unsigned num;
2018
		COMMAND_PARSE_NUMBER(uint, args[0], num);
oharboe's avatar
oharboe committed
2019

2020
		reg_cache_t *cache = target->reg_cache;
2021
		count = 0;
zwelch's avatar
zwelch committed
2022
		while (cache)
2023
2024
2025
2026
		{
			int i;
			for (i = 0; i < cache->num_regs; i++)
			{
2027
				if (count++ == (int)num)
2028
2029
2030
2031
2032
2033
2034
2035
2036
				{
					reg = &cache->reg_list[i];
					break;
				}
			}
			if (reg)
				break;
			cache = cache->next;
		}
oharboe's avatar
oharboe committed
2037

2038
2039
2040
2041
2042
2043
2044
2045
		if (!reg)
		{
			command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
			return ERROR_OK;
		}
	} else /* access a single register by its name */
	{
		reg = register_get_by_name(target->reg_cache, args[0], 1);
oharboe's avatar
oharboe committed
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
		if (!reg)
		{
			command_print(cmd_ctx, "register %s not found in current target", args[0]);
			return ERROR_OK;
		}
	}

	/* display a register */
	if ((argc == 1) || ((argc == 2) && !((args[1][0] >= '0') && (args[1][0] <= '9'))))
	{
		if ((argc == 2) && (strcmp(args[1], "force") == 0))
			reg->valid = 0;
oharboe's avatar
oharboe committed
2059

2060
2061
2062
2063
2064
2065
		if (reg->valid == 0)
		{
			reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
			arch_type->get(reg);
		}
		value = buf_to_str(reg->value, reg->size, 16);
duane's avatar
duane committed
2066
		command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
2067
2068
2069
		free(value);
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2070

2071
2072
2073
	/* set register value */
	if (argc == 2)
	{
2074
		uint8_t *buf = malloc(CEIL(reg->size, 8));
2075
2076
2077
2078
		str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);

		reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
		arch_type->set(reg, buf);
oharboe's avatar
oharboe committed
2079

2080
		value = buf_to_str(reg->value, reg->size, 16);
duane's avatar
duane committed
2081
		command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
2082
		free(value);
oharboe's avatar
oharboe committed
2083

2084
		free(buf);
oharboe's avatar
oharboe committed
2085

2086
2087
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2088

2089
	command_print(cmd_ctx, "usage: reg <#|name> [value]");
oharboe's avatar
oharboe committed
2090

2091
2092
2093
	return ERROR_OK;
}

2094
static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2095
{
2096
	int retval = ERROR_OK;
2097
2098
2099
2100
	target_t *target = get_current_target(cmd_ctx);

	if (argc == 0)
	{
2101
		command_print(cmd_ctx, "background polling: %s",
2102
				jtag_poll_get_enabled() ? "on" : "off");
zwelch's avatar
zwelch committed
2103
2104
2105
2106
2107
		command_print(cmd_ctx, "TAP: %s (%s)",
				target->tap->dotted_name,
				target->tap->enabled ? "enabled" : "disabled");
		if (!target->tap->enabled)
			return ERROR_OK;
2108
		if ((retval = target_poll(target)) != ERROR_OK)
2109
			return retval;
2110
		if ((retval = target_arch_state(target)) != ERROR_OK)
2111
2112
			return retval;

2113
	}
zwelch's avatar
zwelch committed
2114
	else if (argc == 1)
2115
2116
2117
	{
		if (strcmp(args[0], "on") == 0)
		{
2118
			jtag_poll_set_enabled(true);
2119
2120
2121
		}
		else if (strcmp(args[0], "off") == 0)
		{
2122
			jtag_poll_set_enabled(false);
2123
2124
2125
2126
2127
		}
		else
		{
			command_print(cmd_ctx, "arg is \"on\" or \"off\"");
		}
2128
2129
2130
	} else
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
2131
	}
oharboe's avatar
oharboe committed
2132

2133
	return retval;
2134
2135
}

2136
static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2137
{
2138
2139
	if (argc > 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2140

2141
2142
	unsigned ms = 5000;
	if (1 == argc)
2143
	{
2144
2145
		int retval = parse_uint(args[0], &ms);
		if (ERROR_OK != retval)
2146
2147
		{
			command_print(cmd_ctx, "usage: %s [seconds]", cmd);
2148
			return ERROR_COMMAND_SYNTAX_ERROR;
2149
		}
2150
2151
		// convert seconds (given) to milliseconds (needed)
		ms *= 1000;
2152
2153
	}

2154
	target_t *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2155
	return target_wait_state(target, TARGET_HALTED, ms);
2156
2157
}

2158
2159
2160
2161
2162
2163
/* 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
 */
2164
int target_wait_state(target_t *target, enum target_state state, int ms)
2165
2166
{
	int retval;
zwelch's avatar
zwelch committed
2167
2168
	long long then = 0, cur;
	int once = 1;
oharboe's avatar
oharboe committed
2169

2170
2171
	for (;;)
	{
zwelch's avatar
zwelch committed
2172
		if ((retval = target_poll(target)) != ERROR_OK)
2173
2174
2175
2176
2177
			return retval;
		if (target->state == state)
		{
			break;
		}
2178
		cur = timeval_ms();
2179
2180
		if (once)
		{
zwelch's avatar
zwelch committed
2181
			once = 0;
2182
			then = timeval_ms();
2183
			LOG_DEBUG("waiting for target %s...",
2184
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
2185
		}
oharboe's avatar
oharboe committed
2186

zwelch's avatar
zwelch committed
2187
		if (cur-then > 500)
2188
2189
2190
2191
		{
			keep_alive();
		}

zwelch's avatar
zwelch committed
2192
		if ((cur-then) > ms)
2193
		{
2194
			LOG_ERROR("timed out while waiting for target %s",
2195
				Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
oharboe's avatar
oharboe committed
2196
			return ERROR_FAIL;
2197
2198
		}
	}
oharboe's avatar
oharboe committed
2199

2200
2201
2202
	return ERROR_OK;
}

2203
static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2204
{
2205
	LOG_DEBUG("-");
2206

2207
2208
2209
	target_t *target = get_current_target(cmd_ctx);
	int retval = target_halt(target);
	if (ERROR_OK != retval)
2210
		return retval;
oharboe's avatar
oharboe committed
2211

2212
2213
	if (argc == 1)
	{
2214
2215
2216
2217
2218
		unsigned wait;
		retval = parse_uint(args[0], &wait);
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		if (!wait)
2219
2220
2221
			return ERROR_OK;
	}

2222
2223
2224
	return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
}

2225
static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2226
2227
{
	target_t *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2228

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

oharboe's avatar
   
oharboe committed
2231
	target->type->soft_reset_halt(target);
oharboe's avatar
oharboe committed
2232

2233
2234
2235
	return ERROR_OK;
}

2236
static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2237
{
2238
2239
	if (argc > 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2240

2241
2242
	enum target_reset_mode reset_mode = RESET_RUN;
	if (argc == 1)
2243
	{
2244
		const Jim_Nvp *n;
2245
		n = Jim_Nvp_name2value_simple(nvp_reset_modes, args[0]);
zwelch's avatar
zwelch committed
2246
		if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) {
oharboe's avatar
oharboe committed
2247
			return ERROR_COMMAND_SYNTAX_ERROR;
2248
		}
2249
		reset_mode = n->value;
2250
	}
oharboe's avatar
oharboe committed
2251

2252
	/* reset *all* targets */
2253
	return target_process_reset(cmd_ctx, reset_mode);
2254
2255
}

2256

2257
static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2258
{
2259
	int current = 1;
zwelch's avatar
zwelch committed
2260
2261
	if (argc > 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2262

zwelch's avatar
zwelch committed
2263
2264
	target_t *target = get_current_target(cmd_ctx);
	target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
oharboe's avatar
oharboe committed
2265

zwelch's avatar
zwelch committed
2266
2267
2268
	/* with no args, resume from current pc, addr = 0,
	 * with one arguments, addr = args[0],
	 * handle breakpoints, not debugging */
2269
	uint32_t addr = 0;
zwelch's avatar
zwelch committed
2270
	if (argc == 1)
2271
	{
2272
		COMMAND_PARSE_NUMBER(u32, args[0], addr);
2273
		current = 0;
2274
	}
oharboe's avatar
oharboe committed
2275

2276
	return target_resume(target, current, addr, 1, 0);
2277
2278
}

2279
static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2280
{
zwelch's avatar
zwelch committed
2281
2282
	if (argc > 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2283

2284
	LOG_DEBUG("-");
oharboe's avatar
oharboe committed
2285

zwelch's avatar
zwelch committed
2286
2287
2288
	/* with no args, step from current pc, addr = 0,
	 * with one argument addr = args[0],
	 * handle breakpoints, debugging */
2289
	uint32_t addr = 0;
2290
	int current_pc = 1;
2291
	if (argc == 1)
2292
	{
2293
		COMMAND_PARSE_NUMBER(u32, args[0], addr);
2294
		current_pc = 0;
2295
	}
oharboe's avatar
oharboe committed
2296

zwelch's avatar
zwelch committed
2297
	target_t *target = get_current_target(cmd_ctx);
2298
2299

	return target->type->step(target, current_pc, addr, 1);
2300
2301
}

2302
static void handle_md_output(struct command_context_s *cmd_ctx,
2303
		struct target_s *target, uint32_t address, unsigned size,
2304
		unsigned count, const uint8_t *buffer)
2305
2306
2307
2308
2309
2310
2311
2312
2313
{
	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) {
2314
2315
2316
	case 4: value_fmt = "%8.8x "; break;
	case 2: value_fmt = "%4.2x "; break;
	case 1: value_fmt = "%2.2x "; break;
2317
2318
2319
2320
	default:
		LOG_ERROR("invalid memory read size: %u", size);
		exit(-1);
	}
2321

2322
2323
2324
2325
2326
2327
	for (unsigned i = 0; i < count; i++)
	{
		if (i % line_modulo == 0)
		{
			output_len += snprintf(output + output_len,
					sizeof(output) - output_len,
2328
					"0x%8.8x: ",
duane's avatar
duane committed
2329
					(unsigned)(address + (i*size)));
2330
		}
2331

zwelch's avatar
zwelch committed
2332
		uint32_t value = 0;
2333
		const uint8_t *value_ptr = buffer + i * size;
2334
2335
2336
2337
2338
2339
2340
2341
		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);
2342

2343
2344
2345
2346
2347
2348
2349
		if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
		{
			command_print(cmd_ctx, "%s", output);
			output_len = 0;
		}
	}
}
2350

2351
2352
static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
2353
	if (argc < 1)
2354
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2355

2356
2357
2358
2359
2360
2361
	unsigned size = 0;
	switch (cmd[2]) {
	case 'w': size = 4; break;
	case 'h': size = 2; break;
	case 'b': size = 1; break;
	default: return ERROR_COMMAND_SYNTAX_ERROR;
2362
2363
	}

2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
	bool physical=strcmp(args[0], "phys")==0;
	int (*fn)(struct target_s *target,
			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;
	}
2380

2381
	uint32_t address;
2382
	COMMAND_PARSE_NUMBER(u32, args[0], address);
oharboe's avatar
oharboe committed
2383

2384
2385
	unsigned count = 1;
	if (argc == 2)
2386
		COMMAND_PARSE_NUMBER(uint, args[1], count);
oharboe's avatar
oharboe committed
2387

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

2390
	target_t *target = get_current_target(cmd_ctx);
2391
	int retval = fn(target, address, size, count, buffer);
2392
2393
	if (ERROR_OK == retval)
		handle_md_output(cmd_ctx, target, address, size, count, buffer);
2394
2395

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

oharboe's avatar
oharboe committed
2397
	return retval;
2398
2399
}

2400
static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2401
{
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
	if (argc < 2)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
	bool physical=strcmp(args[0], "phys")==0;
	int (*fn)(struct target_s *target,
			uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
	if (physical)
	{
		argc--;
		args++;
		fn=target_write_phys_memory;
	} else
	{
		fn=target_write_memory;
	}
	if ((argc < 2) || (argc > 3))
oharboe's avatar
oharboe committed
2419
		return ERROR_COMMAND_SYNTAX_ERROR;
2420

2421
	uint32_t address;
2422
	COMMAND_PARSE_NUMBER(u32, args[0], address);
2423

2424
	uint32_t value;
2425
	COMMAND_PARSE_NUMBER(u32, args[1], value);
2426
2427

	unsigned count = 1;
oharboe's avatar
oharboe committed
2428
	if (argc == 3)
2429
		COMMAND_PARSE_NUMBER(uint, args[2], count);
oharboe's avatar
oharboe committed
2430

2431
2432
	target_t *target = get_current_target(cmd_ctx);
	unsigned wordsize;
2433
	uint8_t value_buf[4];
2434
2435
2436
	switch (cmd[2])
	{
		case 'w':
oharboe's avatar
oharboe committed
2437
			wordsize = 4;
2438
2439
2440
			target_buffer_set_u32(target, value_buf, value);
			break;
		case 'h':
oharboe's avatar
oharboe committed
2441
			wordsize = 2;
2442
2443
2444
			target_buffer_set_u16(target, value_buf, value);
			break;
		case 'b':
oharboe's avatar
oharboe committed
2445
			wordsize = 1;
2446
2447
2448
			value_buf[0] = value;
			break;
		default:
oharboe's avatar
oharboe committed
2449
			return ERROR_COMMAND_SYNTAX_ERROR;
2450
	}
2451
	for (unsigned i = 0; i < count; i++)
2452
	{
2453
		int retval = fn(target,
2454
2455
				address + i * wordsize, wordsize, 1, value_buf);
		if (ERROR_OK != retval)
oharboe's avatar
oharboe committed
2456
			return retval;
2457
		keep_alive();
2458
2459
2460
2461
2462
2463
	}

	return ERROR_OK;

}

2464
2465
2466
static int parse_load_image_command_args(struct command_context_s *cmd_ctx,
		char **args, int argc, image_t *image,
		uint32_t *min_address, uint32_t *max_address)
2467
{
2468
	if (argc < 1 || argc > 5)
2469
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2470

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

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

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

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

2499
2500
2501
2502
2503
	return ERROR_OK;
}

static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
2504
	uint8_t *buffer;
2505
2506
2507
2508
	uint32_t buf_cnt;
	uint32_t image_size;
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
2509
2510
2511
	int i;
	image_t image;

2512
	int retval = parse_load_image_command_args(cmd_ctx, args, argc,
2513
2514
2515
2516
2517
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;

	target_t *target = get_current_target(cmd_ctx);
Zachary T Welch's avatar
Zachary T Welch committed
2518
2519
2520

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

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

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

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

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

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

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

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

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

2577
2578
2579
		free(buffer);
	}

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

2587
2588
	image_close(&image);

2589
	return retval;
2590
2591
2592

}

2593
static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2594
2595
{
	fileio_t fileio;
oharboe's avatar
oharboe committed
2596

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


2601
2602
2603
2604
2605
2606
2607
2608
	target_t *target = get_current_target(cmd_ctx);

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

2609
	uint32_t address;
2610
	COMMAND_PARSE_NUMBER(u32, args[1], address);
2611
	uint32_t size;
2612
	COMMAND_PARSE_NUMBER(u32, args[2], size);
2613
2614
2615
2616
2617

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

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

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

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

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

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

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

2653
	return retval;
2654
2655
}

2656
static int handle_verify_image_command_internal(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, int verify)
2657
{
2658
	uint8_t *buffer;
2659
2660
	uint32_t buf_cnt;
	uint32_t image_size;
2661
	int i;
Zachary T Welch's avatar
Zachary T Welch committed
2662
	int retval;
2663
2664
	uint32_t checksum = 0;
	uint32_t mem_checksum = 0;
2665

oharboe's avatar
oharboe committed
2666
2667
	image_t image;

2668
	target_t *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2669

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

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

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

2684
2685
	if (argc >= 2)
	{
2686
		uint32_t addr;
2687
		COMMAND_PARSE_NUMBER(u32, args[1], addr);
2688
		image.base_address = addr;
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
		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
2699
	if ((retval = image_open(&image, args[0], (argc == 3) ? args[2] : NULL)) != ERROR_OK)
2700
	{
2701
		return retval;
2702
	}
oharboe's avatar
oharboe committed
2703

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

oharboe's avatar
oharboe committed
2722
		if (verify)
2723
		{
oharboe's avatar
oharboe committed
2724
			/* calculate checksum of image */
2725
			image_calculate_checksum(buffer, buf_cnt, &checksum);
oharboe's avatar
oharboe committed
2726

oharboe's avatar
oharboe committed
2727
			retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
2728
			if (retval != ERROR_OK)
2729
			{
oharboe's avatar
oharboe committed
2730
2731
				free(buffer);
				break;
2732
			}
oharboe's avatar
oharboe committed
2733

2734
			if (checksum != mem_checksum)
2735
			{
oharboe's avatar
oharboe committed
2736
				/* failed crc checksum, fall back to a binary compare */
2737
				uint8_t *data;
oharboe's avatar
oharboe committed
2738
2739
2740

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

2741
				data = (uint8_t*)malloc(buf_cnt);
oharboe's avatar
oharboe committed
2742
2743
2744
2745
2746

				/* Can we use 32bit word accesses? */
				int size = 1;
				int count = buf_cnt;
				if ((count % 4) == 0)
2747
				{
oharboe's avatar
oharboe committed
2748
2749
2750
					size *= 4;
					count /= 4;
				}
zwelch's avatar
zwelch committed
2751
				retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
oharboe's avatar
oharboe committed
2752
2753
				if (retval == ERROR_OK)
				{
2754
					uint32_t t;
oharboe's avatar
oharboe committed
2755
					for (t = 0; t < buf_cnt; t++)
oharboe's avatar
oharboe committed
2756
					{
oharboe's avatar
oharboe committed
2757
2758
						if (data[t] != buffer[t])
						{
2759
2760
2761
2762
							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
2763
										  buffer[t]);
oharboe's avatar
oharboe committed
2764
2765
							free(data);
							free(buffer);
zwelch's avatar
zwelch committed
2766
							retval = ERROR_FAIL;
oharboe's avatar
oharboe committed
2767
2768
							goto done;
						}
zwelch's avatar
zwelch committed
2769
						if ((t%16384) == 0)
oharboe's avatar
oharboe committed
2770
2771
2772
						{
							keep_alive();
						}
oharboe's avatar
oharboe committed
2773
					}
2774
				}
oharboe's avatar
oharboe committed
2775

oharboe's avatar
oharboe committed
2776
2777
2778
2779
				free(data);
			}
		} else
		{
2780
2781
			command_print(cmd_ctx, "address 0x%08" PRIx32 " length 0x%08" PRIx32 "",
						  image.sections[i].base_address,
duane's avatar
duane committed
2782
						  buf_cnt);
2783
		}
oharboe's avatar
oharboe committed
2784

2785
2786
2787
		free(buffer);
		image_size += buf_cnt;
	}
oharboe's avatar
oharboe committed
2788
done:
Zachary T Welch's avatar
Zachary T Welch committed
2789
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
2790
	{
Zachary T Welch's avatar
Zachary T Welch committed
2791
2792
2793
		command_print(cmd_ctx, "verified %" PRIu32 " bytes "
				"in %fs (%0.3f kb/s)", image_size,
				duration_elapsed(&bench), duration_kbps(&bench, image_size));
2794
	}
oharboe's avatar
oharboe committed
2795

2796
	image_close(&image);
oharboe's avatar
oharboe committed
2797

2798
	return retval;
2799
2800
}

2801
static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
oharboe's avatar
oharboe committed
2802
2803
2804
2805
{
	return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 1);
}

2806
static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
oharboe's avatar
oharboe committed
2807
2808
2809
2810
{
	return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 0);
}