target.c 110 KB
Newer Older
2001
2002
	case 2: value_fmt = "%4.2x "; break;
	case 1: value_fmt = "%2.2x "; break;
2003
2004
2005
2006
	default:
		LOG_ERROR("invalid memory read size: %u", size);
		exit(-1);
	}
2007

2008
2009
2010
2011
2012
2013
2014
2015
	for (unsigned i = 0; i < count; i++)
	{
		if (i % line_modulo == 0)
		{
			output_len += snprintf(output + output_len,
					sizeof(output) - output_len,
					"0x%8.8x: ", address + (i*size));
		}
2016

2017
		u32 value=0;
2018
2019
2020
2021
2022
2023
2024
2025
2026
		const u8 *value_ptr = buffer + i * size;
		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);
2027

2028
2029
2030
2031
2032
2033
2034
		if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
		{
			command_print(cmd_ctx, "%s", output);
			output_len = 0;
		}
	}
}
2035

2036
2037
static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
2038
	if (argc < 1)
2039
		return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed
2040

2041
2042
2043
2044
2045
2046
	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;
2047
2048
	}

2049
2050
2051
2052
	u32 address;
	int retval = parse_u32(args[0], &address);
	if (ERROR_OK != retval)
		return retval;
oharboe's avatar
oharboe committed
2053

2054
2055
	unsigned count = 1;
	if (argc == 2)
2056
2057
2058
2059
2060
	{
		retval = parse_uint(args[1], &count);
		if (ERROR_OK != retval)
			return retval;
	}
oharboe's avatar
oharboe committed
2061

2062
	u8 *buffer = calloc(count, size);
oharboe's avatar
oharboe committed
2063

2064
	target_t *target = get_current_target(cmd_ctx);
2065
	retval = target_read_memory(target,
2066
2067
2068
				address, size, count, buffer);
	if (ERROR_OK == retval)
		handle_md_output(cmd_ctx, target, address, size, count, buffer);
2069
2070

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

oharboe's avatar
oharboe committed
2072
	return retval;
2073
2074
}

2075
static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2076
{
oharboe's avatar
oharboe committed
2077
2078
	 if ((argc < 2) || (argc > 3))
		return ERROR_COMMAND_SYNTAX_ERROR;
2079

2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
	u32 address;
	int retval = parse_u32(args[0], &address);
	if (ERROR_OK != retval)
		return retval;

	u32 value;
	retval = parse_u32(args[1], &value);
	if (ERROR_OK != retval)
		return retval;

	unsigned count = 1;
oharboe's avatar
oharboe committed
2091
	if (argc == 3)
2092
2093
2094
2095
2096
	{
		retval = parse_uint(args[2], &count);
		if (ERROR_OK != retval)
			return retval;
	}
oharboe's avatar
oharboe committed
2097

2098
2099
2100
	target_t *target = get_current_target(cmd_ctx);
	unsigned wordsize;
	u8 value_buf[4];
2101
2102
2103
	switch (cmd[2])
	{
		case 'w':
oharboe's avatar
oharboe committed
2104
			wordsize = 4;
2105
2106
2107
			target_buffer_set_u32(target, value_buf, value);
			break;
		case 'h':
oharboe's avatar
oharboe committed
2108
			wordsize = 2;
2109
2110
2111
			target_buffer_set_u16(target, value_buf, value);
			break;
		case 'b':
oharboe's avatar
oharboe committed
2112
			wordsize = 1;
2113
2114
2115
			value_buf[0] = value;
			break;
		default:
oharboe's avatar
oharboe committed
2116
			return ERROR_COMMAND_SYNTAX_ERROR;
2117
	}
2118
	for (unsigned i = 0; i < count; i++)
2119
	{
2120
		retval = target_write_memory(target,
2121
2122
				address + i * wordsize, wordsize, 1, value_buf);
		if (ERROR_OK != retval)
oharboe's avatar
oharboe committed
2123
			return retval;
2124
		keep_alive();
2125
2126
2127
2128
2129
2130
	}

	return ERROR_OK;

}

2131
static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2132
2133
2134
2135
{
	u8 *buffer;
	u32 buf_cnt;
	u32 image_size;
2136
2137
	u32 min_address=0;
	u32 max_address=0xffffffff;
2138
	int i;
2139
	int retval, retvaltemp;
2140

oharboe's avatar
oharboe committed
2141
2142
	image_t image;

2143
2144
	duration_t duration;
	char *duration_text;
oharboe's avatar
oharboe committed
2145

2146
2147
	target_t *target = get_current_target(cmd_ctx);

2148
	if ((argc < 1)||(argc > 5))
2149
	{
2150
		return ERROR_COMMAND_SYNTAX_ERROR;
2151
	}
oharboe's avatar
oharboe committed
2152

2153
2154
2155
	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
	if (argc >= 2)
	{
2156
2157
2158
2159
2160
		u32 addr;
		retval = parse_u32(args[1], &addr);
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		image.base_address = addr;
2161
2162
2163
2164
2165
2166
		image.base_address_set = 1;
	}
	else
	{
		image.base_address_set = 0;
	}
oharboe's avatar
oharboe committed
2167
2168


2169
	image.start_address_set = 0;
oharboe's avatar
oharboe committed
2170

2171
2172
	if (argc>=4)
	{
2173
2174
2175
		retval = parse_u32(args[3], &min_address);
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
2176
2177
2178
	}
	if (argc>=5)
	{
2179
2180
2181
2182
2183
		retval = parse_u32(args[4], &max_address);
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		// use size (given) to find max (required)
		max_address += min_address;
2184
	}
oharboe's avatar
oharboe committed
2185

2186
2187
2188
2189
	if (min_address>max_address)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
oharboe's avatar
oharboe committed
2190

2191
	duration_start_measure(&duration);
oharboe's avatar
oharboe committed
2192

2193
2194
2195
2196
	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2197

2198
	image_size = 0x0;
2199
	retval = ERROR_OK;
2200
2201
2202
2203
2204
2205
2206
2207
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
			break;
		}
oharboe's avatar
oharboe committed
2208

2209
2210
2211
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2212
2213
			break;
		}
oharboe's avatar
oharboe committed
2214

2215
2216
		u32 offset=0;
		u32 length=buf_cnt;
oharboe's avatar
oharboe committed
2217

2218
		/* DANGER!!! beware of unsigned comparision here!!! */
oharboe's avatar
oharboe committed
2219

2220
2221
		if ((image.sections[i].base_address+buf_cnt>=min_address)&&
				(image.sections[i].base_address<max_address))
2222
		{
2223
2224
2225
2226
2227
2228
			if (image.sections[i].base_address<min_address)
			{
				/* clip addresses below */
				offset+=min_address-image.sections[i].base_address;
				length-=offset;
			}
oharboe's avatar
oharboe committed
2229

2230
2231
2232
2233
			if (image.sections[i].base_address+buf_cnt>max_address)
			{
				length-=(image.sections[i].base_address+buf_cnt)-max_address;
			}
oharboe's avatar
oharboe committed
2234

2235
2236
2237
2238
2239
2240
2241
			if ((retval = target_write_buffer(target, image.sections[i].base_address+offset, length, buffer+offset)) != ERROR_OK)
			{
				free(buffer);
				break;
			}
			image_size += length;
			command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
2242
		}
oharboe's avatar
oharboe committed
2243

2244
2245
2246
		free(buffer);
	}

2247
2248
2249
2250
2251
2252
	if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
	{
		image_close(&image);
		return retvaltemp;
	}

2253
2254
2255
2256
	if (retval==ERROR_OK)
	{
		command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
	}
2257
	free(duration_text);
oharboe's avatar
oharboe committed
2258

2259
2260
	image_close(&image);

2261
	return retval;
2262
2263
2264

}

2265
static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2266
2267
{
	fileio_t fileio;
oharboe's avatar
oharboe committed
2268

2269
	u8 buffer[560];
2270
	int retvaltemp;
oharboe's avatar
oharboe committed
2271

2272
2273
	duration_t duration;
	char *duration_text;
oharboe's avatar
oharboe committed
2274

2275
2276
2277
2278
2279
2280
2281
2282
	target_t *target = get_current_target(cmd_ctx);

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

2283
2284
2285
2286
2287
2288
2289
2290
2291
	u32 address;
	int retval = parse_u32(args[1], &address);
	if (ERROR_OK != retval)
		return retval;

	u32 size;
	retval = parse_u32(args[2], &size);
	if (ERROR_OK != retval)
		return retval;
2292
2293
2294
2295
2296

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

2298
	duration_start_measure(&duration);
oharboe's avatar
oharboe committed
2299

2300
2301
2302
2303
	while (size > 0)
	{
		u32 size_written;
		u32 this_run_size = (size > 560) ? 560 : size;
oharboe's avatar
oharboe committed
2304

2305
		retval = target_read_buffer(target, address, this_run_size, buffer);
2306
2307
2308
2309
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2310

2311
2312
2313
2314
2315
		retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2316

2317
2318
2319
2320
		size -= this_run_size;
		address += this_run_size;
	}

2321
2322
2323
2324
2325
	if((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
		return retvaltemp;

	if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
		return retvaltemp;
2326

2327
2328
	if (retval==ERROR_OK)
	{
2329
2330
		command_print(cmd_ctx, "dumped %lld byte in %s",
				fileio.size, duration_text);
2331
		free(duration_text);
2332
	}
oharboe's avatar
oharboe committed
2333

2334
	return retval;
2335
2336
}

2337
static int handle_verify_image_command_internal(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, int verify)
2338
2339
2340
2341
2342
{
	u8 *buffer;
	u32 buf_cnt;
	u32 image_size;
	int i;
2343
	int retval, retvaltemp;
2344
2345
2346
	u32 checksum = 0;
	u32 mem_checksum = 0;

oharboe's avatar
oharboe committed
2347
2348
	image_t image;

2349
2350
	duration_t duration;
	char *duration_text;
oharboe's avatar
oharboe committed
2351

2352
	target_t *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2353

2354
2355
	if (argc < 1)
	{
2356
		return ERROR_COMMAND_SYNTAX_ERROR;
2357
	}
oharboe's avatar
oharboe committed
2358

2359
2360
	if (!target)
	{
2361
		LOG_ERROR("no target selected");
2362
		return ERROR_FAIL;
2363
	}
oharboe's avatar
oharboe committed
2364

2365
	duration_start_measure(&duration);
oharboe's avatar
oharboe committed
2366

2367
2368
	if (argc >= 2)
	{
2369
2370
2371
2372
2373
		u32 addr;
		retval = parse_u32(args[1], &addr);
		if (ERROR_OK != retval)
			return ERROR_COMMAND_SYNTAX_ERROR;
		image.base_address = addr;
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
		image.base_address_set = 1;
	}
	else
	{
		image.base_address_set = 0;
		image.base_address = 0x0;
	}

	image.start_address_set = 0;

2384
	if ((retval=image_open(&image, args[0], (argc == 3) ? args[2] : NULL)) != ERROR_OK)
2385
	{
2386
		return retval;
2387
	}
oharboe's avatar
oharboe committed
2388

2389
	image_size = 0x0;
2390
	retval=ERROR_OK;
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
			break;
		}
		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
2402
			break;
2403
		}
oharboe's avatar
oharboe committed
2404

oharboe's avatar
oharboe committed
2405
		if (verify)
2406
		{
oharboe's avatar
oharboe committed
2407
2408
			/* calculate checksum of image */
			image_calculate_checksum( buffer, buf_cnt, &checksum );
oharboe's avatar
oharboe committed
2409

oharboe's avatar
oharboe committed
2410
2411
			retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
			if( retval != ERROR_OK )
2412
			{
oharboe's avatar
oharboe committed
2413
2414
				free(buffer);
				break;
2415
			}
oharboe's avatar
oharboe committed
2416
2417

			if( checksum != mem_checksum )
2418
			{
oharboe's avatar
oharboe committed
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
				/* failed crc checksum, fall back to a binary compare */
				u8 *data;

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

				data = (u8*)malloc(buf_cnt);

				/* Can we use 32bit word accesses? */
				int size = 1;
				int count = buf_cnt;
				if ((count % 4) == 0)
2430
				{
oharboe's avatar
oharboe committed
2431
2432
2433
					size *= 4;
					count /= 4;
				}
zwelch's avatar
zwelch committed
2434
				retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
oharboe's avatar
oharboe committed
2435
2436
				if (retval == ERROR_OK)
				{
2437
					u32 t;
oharboe's avatar
oharboe committed
2438
					for (t = 0; t < buf_cnt; t++)
oharboe's avatar
oharboe committed
2439
					{
oharboe's avatar
oharboe committed
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
						if (data[t] != buffer[t])
						{
							command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
							free(data);
							free(buffer);
							retval=ERROR_FAIL;
							goto done;
						}
						if ((t%16384)==0)
						{
							keep_alive();
						}
oharboe's avatar
oharboe committed
2452
					}
2453
				}
oharboe's avatar
oharboe committed
2454

oharboe's avatar
oharboe committed
2455
2456
2457
2458
2459
				free(data);
			}
		} else
		{
			command_print(cmd_ctx, "address 0x%08x length 0x%08x", image.sections[i].base_address, buf_cnt);
2460
		}
oharboe's avatar
oharboe committed
2461

2462
2463
2464
		free(buffer);
		image_size += buf_cnt;
	}
oharboe's avatar
oharboe committed
2465
done:
2466
2467
2468
2469
2470
2471
2472

	if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
	{
		image_close(&image);
		return retvaltemp;
	}

2473
2474
2475
2476
	if (retval==ERROR_OK)
	{
		command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
	}
2477
	free(duration_text);
oharboe's avatar
oharboe committed
2478

2479
	image_close(&image);
oharboe's avatar
oharboe committed
2480

2481
	return retval;
2482
2483
}

2484
static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
oharboe's avatar
oharboe committed
2485
2486
2487
2488
{
	return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 1);
}

2489
static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
oharboe's avatar
oharboe committed
2490
2491
2492
2493
{
	return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 0);
}

zwelch's avatar
zwelch committed
2494
static int handle_bp_command_list(struct command_context_s *cmd_ctx)
2495
2496
{
	target_t *target = get_current_target(cmd_ctx);
zwelch's avatar
zwelch committed
2497
2498
	breakpoint_t *breakpoint = target->breakpoints;
	while (breakpoint)
2499
	{
zwelch's avatar
zwelch committed
2500
		if (breakpoint->type == BKPT_SOFT)
2501
		{
zwelch's avatar
zwelch committed
2502
2503
2504
2505
2506
2507
			char* buf = buf_to_str(breakpoint->orig_instr,
					breakpoint->length, 16);
			command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s",
					breakpoint->address, breakpoint->length,
					breakpoint->set, buf);
			free(buf);
2508
2509
2510
		}
		else
		{
zwelch's avatar
zwelch committed
2511
2512
			command_print(cmd_ctx, "0x%8.8x, 0x%x, %i",
					breakpoint->address, breakpoint->length, breakpoint->set);
2513
		}
zwelch's avatar
zwelch committed
2514
2515

		breakpoint = breakpoint->next;
2516
	}
zwelch's avatar
zwelch committed
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
	return ERROR_OK;
}

static int handle_bp_command_set(struct command_context_s *cmd_ctx,
		u32 addr, u32 length, int hw)
{
	target_t *target = get_current_target(cmd_ctx);
	int retval = breakpoint_add(target, addr, length, hw);
	if (ERROR_OK == retval)
		command_print(cmd_ctx, "breakpoint set at 0x%8.8x", addr);
2527
	else
zwelch's avatar
zwelch committed
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
		LOG_ERROR("Failure setting breakpoint");
	return retval;
}

static int handle_bp_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
{
	if (argc == 0)
		return handle_bp_command_list(cmd_ctx);

	if (argc < 2 || argc > 3)
2539
2540
	{
		command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
zwelch's avatar
zwelch committed
2541
		return ERROR_COMMAND_SYNTAX_ERROR;
2542
2543
	}

2544
2545
2546
2547
2548
2549
2550
2551
2552
	u32 addr;
	int retval = parse_u32(args[0], &addr);
	if (ERROR_OK != retval)
		return retval;

	u32 length;
	retval = parse_u32(args[1], &length);
	if (ERROR_OK != retval)
		return retval;
zwelch's avatar
zwelch committed
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563

	int hw = BKPT_SOFT;
	if (argc == 3)
	{
		if (strcmp(args[2], "hw") == 0)
			hw = BKPT_HARD;
		else
			return ERROR_COMMAND_SYNTAX_ERROR;
	}

	return handle_bp_command_set(cmd_ctx, addr, length, hw);
2564
2565
}

2566
static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2567
{
2568
2569
	if (argc != 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
2570

2571
2572
2573
2574
2575
2576
2577
	u32 addr;
	int retval = parse_u32(args[0], &addr);
	if (ERROR_OK != retval)
		return retval;

	target_t *target = get_current_target(cmd_ctx);
	breakpoint_remove(target, addr);
2578
2579
2580
2581

	return ERROR_OK;
}

2582
static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2583
2584
2585
2586
2587
2588
2589
2590
2591
{
	target_t *target = get_current_target(cmd_ctx);

	if (argc == 0)
	{
		watchpoint_t *watchpoint = target->watchpoints;

		while (watchpoint)
		{
ntfreak's avatar
ntfreak committed
2592
			command_print(cmd_ctx, "address: 0x%8.8x, len: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
2593
2594
			watchpoint = watchpoint->next;
		}
2595
		return ERROR_OK;
oharboe's avatar
oharboe committed
2596
2597
	}

2598
2599
2600
2601
2602
2603
	enum watchpoint_rw type = WPT_ACCESS;
	u32 addr = 0;
	u32 length = 0;
	u32 data_value = 0x0;
	u32 data_mask = 0xffffffff;
	int retval;
oharboe's avatar
oharboe committed
2604

2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
	switch (argc)
	{
	case 5:
		retval = parse_u32(args[4], &data_mask);
		if (ERROR_OK != retval)
			return retval;
		// fall through
	case 4:
		retval = parse_u32(args[3], &data_value);
		if (ERROR_OK != retval)
			return retval;
		// fall through
	case 3:
		switch(args[2][0])
2619
		{
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
		case 'r':
			type = WPT_READ;
			break;
		case 'w':
			type = WPT_WRITE;
			break;
		case 'a':
			type = WPT_ACCESS;
			break;
		default:
			LOG_ERROR("invalid watchpoint mode ('%c')", args[2][0]);
			return ERROR_COMMAND_SYNTAX_ERROR;
2632
		}
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
		// fall through
	case 2:
		retval = parse_u32(args[1], &length);
		if (ERROR_OK != retval)
			return retval;
		retval = parse_u32(args[0], &addr);
		if (ERROR_OK != retval)
			return retval;
		break;

	default:
2644
		command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
2645
		return ERROR_COMMAND_SYNTAX_ERROR;
2646
	}
oharboe's avatar
oharboe committed
2647

2648
2649
2650
2651
2652
2653
	retval = watchpoint_add(target, addr, length, type,
			data_value, data_mask);
	if (ERROR_OK != retval)
		LOG_ERROR("Failure setting watchpoints");

	return retval;
2654
2655
}

2656
static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2657
{
2658
2659
	if (argc != 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
2660

2661
2662
2663
2664
2665
	u32 addr;
	int retval = parse_u32(args[0], &addr);
	if (ERROR_OK != retval)
		return retval;

2666
	target_t *target = get_current_target(cmd_ctx);
2667
	watchpoint_remove(target, addr);
oharboe's avatar
oharboe committed
2668

2669
2670
2671
2672
	return ERROR_OK;
}


2673
2674
2675
2676
2677
2678
2679
2680
2681
/**
 * Translate a virtual address to a physical address.
 *
 * The low-level target implementation must have logged a detailed error
 * which is forwarded to telnet/GDB session.
 */
static int handle_virt2phys_command(command_context_t *cmd_ctx,
		char *cmd, char **args, int argc)
{
2682
2683
2684
	if (argc != 1)
		return ERROR_COMMAND_SYNTAX_ERROR;

2685
2686
2687
2688
2689
	target_t *target = get_current_target(cmd_ctx);
	u32 va = strtoul(args[0], NULL, 0);
	u32 pa;

	int retval = target->type->virt2phys(target, va, &pa);
2690
2691
	if (retval == ERROR_OK)
		command_print(cmd_ctx, "Physical address 0x%08x", pa);
2692

2693
2694
	return retval;
}
2695

2696
2697
static void writeData(FILE *f, const void *data, size_t len)
{
2698
	size_t written = fwrite(data, 1, len, f);
2699
	if (written != len)
2700
		LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
2701
2702
}

2703
2704
2705
2706
2707
2708
static void writeLong(FILE *f, int l)
{
	int i;
	for (i=0; i<4; i++)
	{
		char c=(l>>(i*8))&0xff;
2709
		writeData(f, &c, 1);
2710
	}
oharboe's avatar
oharboe committed
2711

2712
}
2713

2714
2715
static void writeString(FILE *f, char *s)
{
2716
	writeData(f, s, strlen(s));
2717
2718
}

2719
/* Dump a gmon.out histogram file. */
2720
static void writeGmon(u32 *samples, u32 sampleNum, char *filename)
2721
{
2722
	u32 i;
2723
2724
2725
	FILE *f=fopen(filename, "w");
	if (f==NULL)
		return;
2726
	writeString(f, "gmon");
2727
2728
2729
2730
	writeLong(f, 0x00000001); /* Version */
	writeLong(f, 0); /* padding */
	writeLong(f, 0); /* padding */
	writeLong(f, 0); /* padding */
oharboe's avatar
oharboe committed
2731

2732
2733
	u8 zero = 0;  /* GMON_TAG_TIME_HIST */
	writeData(f, &zero, 1);
2734

2735
	/* figure out bucket size */
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
	u32 min=samples[0];
	u32 max=samples[0];
	for (i=0; i<sampleNum; i++)
	{
		if (min>samples[i])
		{
			min=samples[i];
		}
		if (max<samples[i])
		{
			max=samples[i];
		}
	}

	int addressSpace=(max-min+1);
oharboe's avatar
oharboe committed
2751

2752
2753
	static const u32 maxBuckets = 256 * 1024; /* maximum buckets. */
	u32 length = addressSpace;
2754
2755
	if (length > maxBuckets)
	{
oharboe's avatar
oharboe committed
2756
		length=maxBuckets;
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
	}
	int *buckets=malloc(sizeof(int)*length);
	if (buckets==NULL)
	{
		fclose(f);
		return;
	}
	memset(buckets, 0, sizeof(int)*length);
	for (i=0; i<sampleNum;i++)
	{
		u32 address=samples[i];
		long long a=address-min;
		long long b=length-1;
		long long c=addressSpace-1;
2771
		int index=(a*b)/c; /* danger!!!! int32 overflows */
2772
2773
		buckets[index]++;
	}
oharboe's avatar
oharboe committed
2774

2775
2776
2777
2778
2779
	/* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
	writeLong(f, min); 			/* low_pc */
	writeLong(f, max);			/* high_pc */
	writeLong(f, length);		/* # of samples */
	writeLong(f, 64000000); 	/* 64MHz */
2780
2781
	writeString(f, "seconds");
	for (i=0; i<(15-strlen("seconds")); i++)
2782
		writeData(f, &zero, 1);
2783
	writeString(f, "s");
oharboe's avatar
oharboe committed
2784

2785
	/*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */
oharboe's avatar
oharboe committed
2786

2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
	char *data=malloc(2*length);
	if (data!=NULL)
	{
		for (i=0; i<length;i++)
		{
			int val;
			val=buckets[i];
			if (val>65535)
			{
				val=65535;
			}
			data[i*2]=val&0xff;
			data[i*2+1]=(val>>8)&0xff;
		}
		free(buckets);
2802
		writeData(f, data, length * 2);
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
		free(data);
	} else
	{
		free(buckets);
	}

	fclose(f);
}

/* profiling samples the CPU PC as quickly as OpenOCD is able, which will be used as a random sampling of PC */
2813
static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
2814
2815
2816
{
	target_t *target = get_current_target(cmd_ctx);
	struct timeval timeout, now;
oharboe's avatar
oharboe committed
2817

2818
2819
2820
2821
2822
2823
2824
	gettimeofday(&timeout, NULL);
	if (argc!=2)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
	char *end;
	timeval_add_time(&timeout, strtoul(args[0], &end, 0), 0);
oharboe's avatar
oharboe committed
2825
	if (*end)
2826
2827
2828
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2829

2830
2831
2832
2833
2834
2835
	command_print(cmd_ctx, "Starting profiling. Halting and resuming the target as often as we can...");

	static const int maxSample=10000;
	u32 *samples=malloc(sizeof(u32)*maxSample);
	if (samples==NULL)
		return ERROR_OK;
oharboe's avatar
oharboe committed
2836

2837
2838
	int numSamples=0;
	int retval=ERROR_OK;
2839
	/* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
2840
	reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
oharboe's avatar
oharboe committed
2841

2842
2843
	for (;;)
	{
2844
		target_poll(target);
2845
2846
2847
2848
		if (target->state == TARGET_HALTED)
		{
			u32 t=*((u32 *)reg->value);
			samples[numSamples++]=t;
2849
2850
			retval = target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
			target_poll(target);
2851
			alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
2852
2853
		} else if (target->state == TARGET_RUNNING)
		{
2854
			/* We want to quickly sample the PC. */
2855
2856
2857
2858
2859
			if((retval = target_halt(target)) != ERROR_OK)
			{
				free(samples);
				return retval;
			}
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
		} else
		{
			command_print(cmd_ctx, "Target not halted or running");
			retval=ERROR_OK;
			break;
		}
		if (retval!=ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2870

2871
2872
2873
2874
		gettimeofday(&now, NULL);
		if ((numSamples>=maxSample) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
		{
			command_print(cmd_ctx, "Profiling completed. %d samples.", numSamples);
2875
2876
2877
2878
2879
			if((retval = target_poll(target)) != ERROR_OK)
			{
				free(samples);
				return retval;
			}
2880
2881
			if (target->state == TARGET_HALTED)
			{
2882
				target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
2883
			}
2884
2885
2886
2887
2888
			if((retval = target_poll(target)) != ERROR_OK)
			{
				free(samples);
				return retval;
			}
2889
2890
2891
2892
2893
2894
			writeGmon(samples, numSamples, args[1]);
			command_print(cmd_ctx, "Wrote %s", args[1]);
			break;
		}
	}
	free(samples);
oharboe's avatar
oharboe committed
2895

2896
2897
	return ERROR_OK;
}
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907

static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
{
	char *namebuf;
	Jim_Obj *nameObjPtr, *valObjPtr;
	int result;

	namebuf = alloc_printf("%s(%d)", varname, idx);
	if (!namebuf)
		return JIM_ERR;
oharboe's avatar
oharboe committed
2908

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
	nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
	valObjPtr = Jim_NewIntObj(interp, val);
	if (!nameObjPtr || !valObjPtr)
	{
		free(namebuf);
		return JIM_ERR;
	}

	Jim_IncrRefCount(nameObjPtr);
	Jim_IncrRefCount(valObjPtr);
	result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
	Jim_DecrRefCount(interp, nameObjPtr);
	Jim_DecrRefCount(interp, valObjPtr);
	free(namebuf);
	/* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
	return result;
}

static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	command_context_t *context;
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
	target_t *target;

	context = Jim_GetAssocData(interp, "context");
	if (context == NULL)
	{
		LOG_ERROR("mem2array: no command context");
		return JIM_ERR;
	}
	target = get_current_target(context);
	if (target == NULL)
	{
		LOG_ERROR("mem2array: no current target");
		return JIM_ERR;
	}

2945
	return 	target_mem2array(interp, target, argc-1, argv+1);
2946
2947
2948
2949
}

static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
{
2950
2951
	long l;
	u32 width;
2952
	int len;
2953
2954
2955
2956
2957
	u32 addr;
	u32 count;
	u32 v;
	const char *varname;
	u8 buffer[4096];
2958
2959
	int  n, e, retval;
	u32 i;
2960
2961
2962

	/* argv[1] = name of array to receive the data
	 * argv[2] = desired width
oharboe's avatar
oharboe committed
2963
	 * argv[3] = memory address
2964
2965
	 * argv[4] = count of times to read
	 */
2966
	if (argc != 4) {
2967
2968
2969
		Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
		return JIM_ERR;
	}
2970
	varname = Jim_GetString(argv[0], &len);
2971
2972
	/* given "foo" get space for worse case "foo(%d)" .. add 20 */

2973
	e = Jim_GetLong(interp, argv[1], &l);
2974
2975
2976
2977
	width = l;
	if (e != JIM_OK) {
		return e;
	}
oharboe's avatar
oharboe committed
2978

2979
	e = Jim_GetLong(interp, argv[2], &l);
2980
2981
2982
2983
	addr = l;
	if (e != JIM_OK) {
		return e;
	}
2984
	e = Jim_GetLong(interp, argv[3], &l);
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
	len = l;
	if (e != JIM_OK) {
		return e;
	}
	switch (width) {
		case 8:
			width = 1;
			break;
		case 16:
			width = 2;
			break;
		case 32:
			width = 4;
			break;
		default:
			Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
For faster browsing, not all history is shown. View entire blame