changeset 36:65111e6eee9e

loadtool: dump2bin and dump2srec implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 06 May 2013 02:04:56 +0000
parents 05af070c4b60
children 437f9365249c
files loadtools/ltdispatch.c loadtools/ltdump.c
diffstat 2 files changed, 166 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/loadtools/ltdispatch.c	Sun May 05 02:24:56 2013 +0000
+++ b/loadtools/ltdispatch.c	Mon May 06 02:04:56 2013 +0000
@@ -9,6 +9,8 @@
 #include <stdlib.h>
 
 extern int cmd_crc32();
+extern int cmd_dump2bin();
+extern int cmd_dump2srec();
 extern int cmd_exec();
 extern int cmd_exit();
 extern int loadtool_cmd_passthru();
@@ -21,6 +23,8 @@
 } cmdtab[] = {
 	{"crc32", 2, 2, cmd_crc32},
 	{"dump", 2, 2, loadtool_cmd_passthru},
+	{"dump2bin", 3, 3, cmd_dump2bin},
+	{"dump2srec", 3, 3, cmd_dump2srec},
 	{"exec", 1, 1, cmd_exec},
 	{"exit", 0, 1, cmd_exit},
 	{"quit", 0, 1, cmd_exit},
--- a/loadtools/ltdump.c	Sun May 05 02:24:56 2013 +0000
+++ b/loadtools/ltdump.c	Mon May 06 02:04:56 2013 +0000
@@ -10,6 +10,7 @@
 #include <strings.h>
 #include <stdlib.h>
 
+extern uint32_t crc32_table[];
 extern char target_response_line[];
 
 crc32_on_target(area_base, area_len, retptr)
@@ -63,9 +64,170 @@
 	return(stat);
 }
 
+/* the actual dump facility */
+
+static FILE *dump_outfile;
+static int dump_save_srec;
+static uint32_t dump_nextaddr, dump_crcaccum;
+static u_char dump_binrec[0x86];
+
+static
+dump_receiver(line)
+	char *line;
+{
+	int i, b;
+	u_char sr_cksum;
+	uint32_t addr_from_srec;
+
+	if (strncmp(line, "S385", 4)) {
+		fprintf(stderr,
+			"error: target response is not the expected S385...\n");
+		return(-1);
+	}
+	for (i = 0; i < 0x86; i++) {
+		b = decode_hex_byte(line + i*2 + 2);
+		if (b < 0) {
+			fprintf(stderr,
+			"data from target: S-record hex decode error\n");
+			return(-1);
+		}
+		dump_binrec[i] = b;
+	}
+	sr_cksum = 0;
+	for (i = 0; i < 0x86; i++)
+		sr_cksum += dump_binrec[i];
+	if (sr_cksum != 0xFF) {
+		fprintf(stderr, "data from target: bad S-record checksum\n");
+		return(-1);
+	}
+	/* basic S-record format OK; now verify the address */
+	addr_from_srec = ((uint32_t) dump_binrec[1] << 24) |
+			 ((uint32_t) dump_binrec[2] << 16) |
+			 ((uint32_t) dump_binrec[3] << 8) |
+			  (uint32_t) dump_binrec[4];
+	if (addr_from_srec != dump_nextaddr) {
+		fprintf(stderr,
+			"error: S3 record from target has the wrong address\n");
+		return(-1);
+	}
+	/* all checks passed - save it */
+	if (dump_save_srec)
+		fprintf(dump_outfile, "%s\n", line);
+	else
+		fwrite(dump_binrec + 5, 1, 0x80, dump_outfile);
+	/* update running CRC */
+	for (i = 0; i < 0x80; i++)
+		dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^
+						dump_binrec[i+5]] ^
+				(dump_crcaccum >> 8);
+	/* progress indication */
+	putchar('.');
+	fflush(stdout);
+	dump_nextaddr += 0x80;
+	return(1);
+}
+
+loadtool_memdump(start_addr, area_len, filename, fmt_srec)
+	u_long start_addr, area_len;
+	char *filename;
+{
+	u_long target_crc_init, target_crc_fin;
+	char *target_argv[4], target_arg1[10], target_arg2[10];
+	int stat;
+
+	if (start_addr & 0x7F || area_len & 0x7F) {
+		fprintf(stderr,
+		"error: implementation limit: 128-byte alignment required\n");
+		return(-1);
+	}
+	printf("Requesting initial CRC-32 of the area from target...\n");
+	stat = crc32_on_target(start_addr, area_len, &target_crc_init);
+	if (stat)
+		return(stat);
+	printf("got %08lX\n", target_crc_init);
+	dump_outfile = fopen(filename, "w");
+	if (!dump_outfile) {
+		perror(filename);
+		return(-1);
+	}
+	dump_save_srec = fmt_srec;
+	dump_nextaddr = start_addr;
+	dump_crcaccum = 0xFFFFFFFF;
+
+	printf("Requesting memory dump...\n");
+	sprintf(target_arg1, "%lx", start_addr);
+	sprintf(target_arg2, "%lx", area_len);
+	target_argv[0] = "DUMP";
+	target_argv[1] = target_arg1;
+	target_argv[2] = target_arg2;
+	target_argv[3] = 0;
+	tpinterf_make_cmd(target_argv);
+	stat = tpinterf_send_cmd();
+	if (stat < 0) {
+		fclose(dump_outfile);
+		return(stat);
+	}
+	stat = tpinterf_capture_output(2, dump_receiver);
+	fclose(dump_outfile);
+	if (stat < 0)
+		return(stat);
+	putchar('\n');	/* after lots of dots */
+
+	/* sanity checks */
+	if (dump_nextaddr != start_addr + area_len) {
+		fprintf(stderr,
+		"error: received dump length does not match expected\n");
+		return(-1);
+	}
+	if (dump_crcaccum != (uint32_t) target_crc_init) {
+		fprintf(stderr, "error: CRC mismatch (computed %lX)\n",
+			(u_long) dump_crcaccum);
+		return(-1);
+	}
+	printf("Requesting another CRC-32 of the area from target...\n");
+	stat = crc32_on_target(start_addr, area_len, &target_crc_fin);
+	if (stat)
+		return(stat);
+	if (target_crc_fin == target_crc_init) {
+		printf("match, dump successful\n");
+		return(0);
+	} else {
+		fprintf(stderr, "mismatch: got %lX this time\n",
+			target_crc_fin);
+		return(-1);
+	}
+}
+
 cmd_dump2bin(argc, argv)
 	char **argv;
 {
+	u_long area_base, area_len;
+	char *strtoul_endp;
 
+	area_base = strtoul(argv[1], &strtoul_endp, 16);
+	if (*strtoul_endp) {
+inv:		fprintf(stderr, "usage: dump2bin hex-start hex-len outfile\n");
+		return(-1);
+	}
+	area_len = strtoul(argv[2], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	return loadtool_memdump(area_base, area_len, argv[3], 0);
+}
 
+cmd_dump2srec(argc, argv)
+	char **argv;
+{
+	u_long area_base, area_len;
+	char *strtoul_endp;
+
+	area_base = strtoul(argv[1], &strtoul_endp, 16);
+	if (*strtoul_endp) {
+inv:		fprintf(stderr, "usage: dump2srec hex-start hex-len outfile\n");
+		return(-1);
+	}
+	area_len = strtoul(argv[2], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	return loadtool_memdump(area_base, area_len, argv[3], 1);
 }