target.c 69.2 KB
Newer Older
2001
2002
2003
2004
2005
2006

}

int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	fileio_t fileio;
oharboe's avatar
oharboe committed
2007

2008
2009
2010
	u32 address;
	u32 size;
	u8 buffer[560];
2011
	int retval=ERROR_OK;
oharboe's avatar
oharboe committed
2012

2013
2014
	duration_t duration;
	char *duration_text;
oharboe's avatar
oharboe committed
2015

2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
	target_t *target = get_current_target(cmd_ctx);

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

	address = strtoul(args[1], NULL, 0);
	size = strtoul(args[2], NULL, 0);

	if ((address & 3) || (size & 3))
	{
		command_print(cmd_ctx, "only 32-bit aligned address and size are supported");
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2032

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

2038
	duration_start_measure(&duration);
oharboe's avatar
oharboe committed
2039

2040
2041
2042
2043
	while (size > 0)
	{
		u32 size_written;
		u32 this_run_size = (size > 560) ? 560 : size;
oharboe's avatar
oharboe committed
2044

2045
2046
2047
2048
2049
		retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2050

2051
2052
2053
2054
2055
		retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
		if (retval != ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2056

2057
2058
2059
2060
2061
2062
2063
		size -= this_run_size;
		address += this_run_size;
	}

	fileio_close(&fileio);

	duration_stop_measure(&duration, &duration_text);
2064
2065
2066
2067
	if (retval==ERROR_OK)
	{
		command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
	}
2068
	free(duration_text);
oharboe's avatar
oharboe committed
2069

2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
	return ERROR_OK;
}

int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	u8 *buffer;
	u32 buf_cnt;
	u32 image_size;
	int i;
	int retval;
	u32 checksum = 0;
	u32 mem_checksum = 0;

oharboe's avatar
oharboe committed
2083
2084
	image_t image;

2085
2086
	duration_t duration;
	char *duration_text;
oharboe's avatar
oharboe committed
2087

2088
	target_t *target = get_current_target(cmd_ctx);
oharboe's avatar
oharboe committed
2089

2090
2091
	if (argc < 1)
	{
2092
		return ERROR_COMMAND_SYNTAX_ERROR;
2093
	}
oharboe's avatar
oharboe committed
2094

2095
2096
	if (!target)
	{
2097
		LOG_ERROR("no target selected");
2098
		return ERROR_FAIL;
2099
	}
oharboe's avatar
oharboe committed
2100

2101
	duration_start_measure(&duration);
oharboe's avatar
oharboe committed
2102

2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
	if (argc >= 2)
	{
		image.base_address_set = 1;
		image.base_address = strtoul(args[1], NULL, 0);
	}
	else
	{
		image.base_address_set = 0;
		image.base_address = 0x0;
	}

	image.start_address_set = 0;

2116
	if ((retval=image_open(&image, args[0], (argc == 3) ? args[2] : NULL)) != ERROR_OK)
2117
	{
2118
		return retval;
2119
	}
oharboe's avatar
oharboe committed
2120

2121
	image_size = 0x0;
2122
	retval=ERROR_OK;
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
	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);
2134
			break;
2135
		}
oharboe's avatar
oharboe committed
2136

2137
2138
		/* calculate checksum of image */
		image_calculate_checksum( buffer, buf_cnt, &checksum );
oharboe's avatar
oharboe committed
2139

2140
2141
2142
2143
		retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
		if( retval != ERROR_OK )
		{
			free(buffer);
2144
			break;
2145
		}
oharboe's avatar
oharboe committed
2146

2147
2148
2149
2150
		if( checksum != mem_checksum )
		{
			/* failed crc checksum, fall back to a binary compare */
			u8 *data;
oharboe's avatar
oharboe committed
2151

2152
			command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
oharboe's avatar
oharboe committed
2153

2154
			data = (u8*)malloc(buf_cnt);
oharboe's avatar
oharboe committed
2155

2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
			/* Can we use 32bit word accesses? */
			int size = 1;
			int count = buf_cnt;
			if ((count % 4) == 0)
			{
				size *= 4;
				count /= 4;
			}
			retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
			if (retval == ERROR_OK)
			{
				int t;
				for (t = 0; t < buf_cnt; t++)
				{
					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);
2175
2176
						retval=ERROR_FAIL;
						goto done;
2177
2178
2179
					}
				}
			}
oharboe's avatar
oharboe committed
2180

2181
2182
			free(data);
		}
oharboe's avatar
oharboe committed
2183

2184
2185
2186
		free(buffer);
		image_size += buf_cnt;
	}
oharboe's avatar
oharboe committed
2187
done:
2188
	duration_stop_measure(&duration, &duration_text);
2189
2190
2191
2192
	if (retval==ERROR_OK)
	{
		command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
	}
2193
	free(duration_text);
oharboe's avatar
oharboe committed
2194

2195
	image_close(&image);
oharboe's avatar
oharboe committed
2196

2197
	return retval;
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
}

int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	int retval;
	target_t *target = get_current_target(cmd_ctx);

	if (argc == 0)
	{
		breakpoint_t *breakpoint = target->breakpoints;

		while (breakpoint)
		{
			if (breakpoint->type == BKPT_SOFT)
			{
				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);
			}
			else
			{
				command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);
			}
			breakpoint = breakpoint->next;
		}
	}
	else if (argc >= 2)
	{
		int hw = BKPT_SOFT;
		u32 length = 0;

		length = strtoul(args[1], NULL, 0);
oharboe's avatar
oharboe committed
2230

2231
2232
2233
2234
2235
2236
		if (argc >= 3)
			if (strcmp(args[2], "hw") == 0)
				hw = BKPT_HARD;

		if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)
		{
2237
			LOG_ERROR("Failure setting breakpoints");
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
		}
		else
		{
			command_print(cmd_ctx, "breakpoint added at address 0x%8.8x", strtoul(args[0], NULL, 0));
		}
	}
	else
	{
		command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
	}

	return ERROR_OK;
}

int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	target_t *target = get_current_target(cmd_ctx);

	if (argc > 0)
		breakpoint_remove(target, strtoul(args[0], NULL, 0));

	return ERROR_OK;
}

int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	target_t *target = get_current_target(cmd_ctx);
	int retval;

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

		while (watchpoint)
		{
ntfreak's avatar
ntfreak committed
2273
			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);
2274
2275
			watchpoint = watchpoint->next;
		}
oharboe's avatar
oharboe committed
2276
	}
2277
2278
2279
2280
2281
	else if (argc >= 2)
	{
		enum watchpoint_rw type = WPT_ACCESS;
		u32 data_value = 0x0;
		u32 data_mask = 0xffffffff;
oharboe's avatar
oharboe committed
2282

2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
		if (argc >= 3)
		{
			switch(args[2][0])
			{
				case 'r':
					type = WPT_READ;
					break;
				case 'w':
					type = WPT_WRITE;
					break;
				case 'a':
					type = WPT_ACCESS;
					break;
				default:
					command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
					return ERROR_OK;
			}
		}
		if (argc >= 4)
		{
			data_value = strtoul(args[3], NULL, 0);
		}
		if (argc >= 5)
		{
			data_mask = strtoul(args[4], NULL, 0);
		}
oharboe's avatar
oharboe committed
2309

2310
2311
2312
		if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
				strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
		{
2313
			LOG_ERROR("Failure setting breakpoints");
2314
2315
2316
2317
2318
2319
		}
	}
	else
	{
		command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
	}
oharboe's avatar
oharboe committed
2320

2321
2322
2323
2324
2325
2326
2327
2328
2329
	return ERROR_OK;
}

int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	target_t *target = get_current_target(cmd_ctx);

	if (argc > 0)
		watchpoint_remove(target, strtoul(args[0], NULL, 0));
oharboe's avatar
oharboe committed
2330

2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
	return ERROR_OK;
}

int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
{
	int retval;
	target_t *target = get_current_target(cmd_ctx);
	u32 va;
	u32 pa;

	if (argc != 1)
	{
		return ERROR_COMMAND_SYNTAX_ERROR;
	}
	va = strtoul(args[0], NULL, 0);

	retval = target->type->virt2phys(target, va, &pa);
	if (retval == ERROR_OK)
	{
		command_print(cmd_ctx, "Physical address 0x%08x", pa);
	}
	else
	{
oharboe's avatar
oharboe committed
2354
2355
		/* lower levels will have logged a detailed error which is
		 * forwarded to telnet/GDB session.
2356
2357
2358
2359
		 */
	}
	return retval;
}
2360
2361
2362
2363
2364
2365
static void writeLong(FILE *f, int l)
{
	int i;
	for (i=0; i<4; i++)
	{
		char c=(l>>(i*8))&0xff;
oharboe's avatar
oharboe committed
2366
		fwrite(&c, 1, 1, f);
2367
	}
oharboe's avatar
oharboe committed
2368

2369
2370
2371
}
static void writeString(FILE *f, char *s)
{
oharboe's avatar
oharboe committed
2372
	fwrite(s, 1, strlen(s), f);
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
}



// Dump a gmon.out histogram file.
static void writeGmon(u32 *samples, int sampleNum, char *filename)
{
	int i;
	FILE *f=fopen(filename, "w");
	if (f==NULL)
		return;
	fwrite("gmon", 1, 4, f);
	writeLong(f, 0x00000001); // Version
	writeLong(f, 0); // padding
	writeLong(f, 0); // padding
	writeLong(f, 0); // padding
oharboe's avatar
oharboe committed
2389
2390

	fwrite("", 1, 1, f);  // GMON_TAG_TIME_HIST
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407

	// figure out bucket size
	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
2408

2409
2410
2411
2412
	static int const maxBuckets=256*1024; // maximum buckets.
	int length=addressSpace;
	if (length > maxBuckets)
	{
oharboe's avatar
oharboe committed
2413
		length=maxBuckets;
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
	}
	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;
oharboe's avatar
oharboe committed
2428
		int index=(a*b)/c; // danger!!!! int32 overflows
2429
2430
		buckets[index]++;
	}
oharboe's avatar
oharboe committed
2431

2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
	//			   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
	writeString(f, "seconds");
	for (i=0; i<(15-strlen("seconds")); i++)
	{
		fwrite("", 1, 1, f);  // padding
	}
	writeString(f, "s");
oharboe's avatar
oharboe committed
2443

2444
//			   append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size)
oharboe's avatar
oharboe committed
2445

2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
	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);
		fwrite(data, 1, length*2, f);
		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 */
int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	target_t *target = get_current_target(cmd_ctx);
	struct timeval timeout, now;
oharboe's avatar
oharboe committed
2476

2477
2478
2479
2480
2481
2482
2483
	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
2484
	if (*end)
2485
2486
2487
	{
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
2488

2489
2490
2491
2492
2493
2494
	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
2495

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

2501
2502
	for (;;)
	{
2503
		target_poll(target);
2504
2505
2506
2507
		if (target->state == TARGET_HALTED)
		{
			u32 t=*((u32 *)reg->value);
			samples[numSamples++]=t;
2508
2509
			retval = target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
			target_poll(target);
2510
2511
2512
2513
			usleep(10*1000); // sleep 10ms, i.e. <100 samples/second.
		} else if (target->state == TARGET_RUNNING)
		{
			// We want to quickly sample the PC.
2514
			target_halt(target);
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
		} else
		{
			command_print(cmd_ctx, "Target not halted or running");
			retval=ERROR_OK;
			break;
		}
		if (retval!=ERROR_OK)
		{
			break;
		}
oharboe's avatar
oharboe committed
2525

2526
2527
2528
2529
		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);
2530
			target_poll(target);
2531
2532
			if (target->state == TARGET_HALTED)
			{
2533
				target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
2534
			}
2535
			target_poll(target);
2536
2537
2538
2539
2540
2541
			writeGmon(samples, numSamples, args[1]);
			command_print(cmd_ctx, "Wrote %s", args[1]);
			break;
		}
	}
	free(samples);
oharboe's avatar
oharboe committed
2542

2543
2544
	return ERROR_OK;
}
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554

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
2555

2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
	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)
{
	target_t *target;
	command_context_t *context;
	long l;
	u32 width;
	u32 len;
	u32 addr;
	u32 count;
	u32 v;
	const char *varname;
	u8 buffer[4096];
	int  i, n, e, retval;

	/* argv[1] = name of array to receive the data
	 * argv[2] = desired width
oharboe's avatar
oharboe committed
2590
	 * argv[3] = memory address
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
	 * argv[4] = count of times to read
	 */
	if (argc != 5) {
		Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
		return JIM_ERR;
	}
	varname = Jim_GetString(argv[1], &len);
	/* given "foo" get space for worse case "foo(%d)" .. add 20 */

	e = Jim_GetLong(interp, argv[2], &l);
	width = l;
	if (e != JIM_OK) {
		return e;
	}
oharboe's avatar
oharboe committed
2605

2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
	e = Jim_GetLong(interp, argv[3], &l);
	addr = l;
	if (e != JIM_OK) {
		return e;
	}
	e = Jim_GetLong(interp, argv[4], &l);
	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));
			Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
			return JIM_ERR;
	}
	if (len == 0) {
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
		Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
		return JIM_ERR;
	}
	if ((addr + (len * width)) < addr) {
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
		Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
		return JIM_ERR;
	}
	/* absurd transfer size? */
	if (len > 65536) {
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
		Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
		return JIM_ERR;
oharboe's avatar
oharboe committed
2646
2647
	}

2648
2649
2650
2651
2652
2653
2654
	if ((width == 1) ||
		((width == 2) && ((addr & 1) == 0)) ||
		((width == 4) && ((addr & 3) == 0))) {
		/* all is well */
	} else {
		char buf[100];
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
oharboe's avatar
oharboe committed
2655
		sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
		Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
		return JIM_ERR;
	}

	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;
	}
oharboe's avatar
oharboe committed
2672

2673
2674
2675
2676
2677
2678
2679
2680
	/* Transfer loop */

	/* index counter */
	n = 0;
	/* assume ok */
	e = JIM_OK;
	while (len) {
		/* Slurp... in buffer size chunks */
oharboe's avatar
oharboe committed
2681

2682
2683
2684
2685
		count = len; /* in objects.. */
		if (count > (sizeof(buffer)/width)) {
			count = (sizeof(buffer)/width);
		}
oharboe's avatar
oharboe committed
2686

2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
		retval = target->type->read_memory( target, addr, width, count, buffer );
		if (retval != ERROR_OK) {
			/* BOO !*/
			LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
			Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
			Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
			e = JIM_ERR;
			len = 0;
		} else {
			v = 0; /* shut up gcc */
			for (i = 0 ;i < count ;i++, n++) {
				switch (width) {
					case 4:
						v = target_buffer_get_u32(target, &buffer[i*width]);
						break;
					case 2:
						v = target_buffer_get_u16(target, &buffer[i*width]);
						break;
					case 1:
						v = buffer[i] & 0x0ff;
						break;
				}
				new_int_array_element(interp, varname, n, v);
			}
			len -= count;
		}
	}
oharboe's avatar
oharboe committed
2714

2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
	Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));

	return JIM_OK;
}

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

	namebuf = alloc_printf("%s(%d)", varname, idx);
	if (!namebuf)
		return JIM_ERR;

	nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
	if (!nameObjPtr)
	{
		free(namebuf);
		return JIM_ERR;
	}

	Jim_IncrRefCount(nameObjPtr);
	valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
	Jim_DecrRefCount(interp, nameObjPtr);
	free(namebuf);
	if (valObjPtr == NULL)
		return JIM_ERR;

	result = Jim_GetLong(interp, valObjPtr, &l);
	/* printf("%s(%d) => 0%08x\n", varname, idx, val); */
	*val = l;
	return result;
}

static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	target_t *target;
	command_context_t *context;
	long l;
	u32 width;
	u32 len;
	u32 addr;
	u32 count;
	u32 v;
	const char *varname;
	u8 buffer[4096];
2763
	int  i, n, e, retval;
2764
2765
2766

	/* argv[1] = name of array to get the data
	 * argv[2] = desired width
oharboe's avatar
oharboe committed
2767
	 * argv[3] = memory address
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
	 * argv[4] = count to write
	 */
	if (argc != 5) {
		Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
		return JIM_ERR;
	}
	varname = Jim_GetString(argv[1], &len);
	/* given "foo" get space for worse case "foo(%d)" .. add 20 */

	e = Jim_GetLong(interp, argv[2], &l);
	width = l;
	if (e != JIM_OK) {
		return e;
	}
oharboe's avatar
oharboe committed
2782

2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
	e = Jim_GetLong(interp, argv[3], &l);
	addr = l;
	if (e != JIM_OK) {
		return e;
	}
	e = Jim_GetLong(interp, argv[4], &l);
	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));
			Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
			return JIM_ERR;
	}
	if (len == 0) {
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
		Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
		return JIM_ERR;
	}
	if ((addr + (len * width)) < addr) {
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
		Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
		return JIM_ERR;
	}
	/* absurd transfer size? */
	if (len > 65536) {
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
		Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
		return JIM_ERR;
oharboe's avatar
oharboe committed
2823
2824
	}

2825
2826
2827
2828
2829
2830
2831
	if ((width == 1) ||
		((width == 2) && ((addr & 1) == 0)) ||
		((width == 4) && ((addr & 3) == 0))) {
		/* all is well */
	} else {
		char buf[100];
		Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
oharboe's avatar
oharboe committed
2832
		sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
		Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
		return JIM_ERR;
	}

	context = Jim_GetAssocData(interp, "context");
	if (context == NULL)
	{
		LOG_ERROR("array2mem: no command context");
		return JIM_ERR;
	}
	target = get_current_target(context);
	if (target == NULL)
	{
		LOG_ERROR("array2mem: no current target");
		return JIM_ERR;
	}
oharboe's avatar
oharboe committed
2849

2850
2851
2852
2853
2854
2855
2856
2857
	/* Transfer loop */

	/* index counter */
	n = 0;
	/* assume ok */
	e = JIM_OK;
	while (len) {
		/* Slurp... in buffer size chunks */
oharboe's avatar
oharboe committed
2858

2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
		count = len; /* in objects.. */
		if (count > (sizeof(buffer)/width)) {
			count = (sizeof(buffer)/width);
		}

		v = 0; /* shut up gcc */
		for (i = 0 ;i < count ;i++, n++) {
			get_int_array_element(interp, varname, n, &v);
			switch (width) {
			case 4:
				target_buffer_set_u32(target, &buffer[i*width], v);
				break;
			case 2:
				target_buffer_set_u16(target, &buffer[i*width], v);
				break;
			case 1:
				buffer[i] = v & 0x0ff;
				break;
			}
		}
		len -= count;

		retval = target->type->write_memory(target, addr, width, count, buffer);
		if (retval != ERROR_OK) {
			/* BOO !*/
			LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
			Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
			Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
			e = JIM_ERR;
			len = 0;
		}
	}
oharboe's avatar
oharboe committed
2891

2892
2893
2894
2895
	Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));

	return JIM_OK;
}
For faster browsing, not all history is shown. View entire blame