diff loadtools/ltdump.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 98474043ecdd
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/ltdump.c	Sat Jun 11 00:13:35 2016 +0000
@@ -0,0 +1,257 @@
+/*
+ * This module implements the dump2bin and dump2srec functionality
+ * of fc-loadtool.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <time.h>
+
+extern uint32_t crc32_table[];
+extern char target_response_line[];
+
+crc32_on_target(area_base, area_len, retptr)
+	u_long area_base, area_len, *retptr;
+{
+	char arg1[10], arg2[10], *argv[4];
+	int stat;
+	char *strtoul_endp;
+
+	sprintf(arg1, "%lx", area_base);
+	sprintf(arg2, "%lx", area_len);
+	argv[0] = "crc32";
+	argv[1] = arg1;
+	argv[2] = arg2;
+	argv[3] = 0;
+	tpinterf_make_cmd(argv);
+	if (tpinterf_send_cmd() < 0)
+		return(-1);
+	stat = tpinterf_capture_output_oneline(10);	/* 10 s timeout */
+	if (stat != 1) {
+errout:		fprintf(stderr, "error: malformed response to crc32 command\n");
+		return(-1);
+	}
+	if (strlen(target_response_line) != 8)
+		goto errout;
+	*retptr = strtoul(target_response_line, &strtoul_endp, 16);
+	if (strtoul_endp != target_response_line + 8)
+		goto errout;
+	return(0);
+}
+
+cmd_crc32(argc, argv)
+	char **argv;
+{
+	u_long area_base, area_len;
+	char *strtoul_endp;
+	u_long crc_result;
+	int stat;
+
+	area_base = strtoul(argv[1], &strtoul_endp, 16);
+	if (*strtoul_endp) {
+inv:		fprintf(stderr, "usage: crc32 hex-start hex-len\n");
+		return(-1);
+	}
+	area_len = strtoul(argv[2], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	stat = crc32_on_target(area_base, area_len, &crc_result);
+	if (stat == 0)
+		printf("%08lX\n", crc_result);
+	return(stat);
+}
+
+/* the actual dump facility */
+
+static FILE *dump_outfile;
+static int dump_save_srec;
+static uint32_t dump_nextaddr, dump_crcaccum;
+static uint32_t dump_total_len, dump_progress_len;
+static u_char dump_binrec[0x86];
+static time_t dump_last_time;
+
+static char dumpsrec_s0_line[] = "S007000044554D50C2\n";
+static char dumpsrec_s7_line[] = "S70500000000FA\n";
+
+static
+dump_receiver(line)
+	char *line;
+{
+	int i, b;
+	u_char sr_cksum;
+	uint32_t addr_from_srec;
+	time_t curtime;
+
+	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) {
+		if (!dump_progress_len)
+			fputs(dumpsrec_s0_line, dump_outfile);
+		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 */
+	dump_progress_len += 0x80;
+	i = dump_progress_len * 100 / dump_total_len;
+	time(&curtime);
+	if (curtime != dump_last_time || i == 100) {
+		printf("\rRx %lu out of %lu bytes (%i%%)",
+			(u_long) dump_progress_len, (u_long) dump_total_len, i);
+		fflush(stdout);
+	}
+	dump_nextaddr += 0x80;
+	dump_last_time = curtime;
+	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;
+	dump_total_len = area_len;
+	dump_progress_len = 0;
+
+	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);
+	if (stat < 0) {
+		fclose(dump_outfile);
+		return(stat);
+	}
+	putchar('\n');	/* after last progress line */
+
+	/* sanity checks */
+	if (dump_nextaddr != start_addr + area_len) {
+		fclose(dump_outfile);
+		fprintf(stderr,
+		"error: received dump length does not match expected\n");
+		return(-1);
+	}
+	if (dump_crcaccum != (uint32_t) target_crc_init) {
+		fclose(dump_outfile);
+		fprintf(stderr, "error: CRC mismatch (computed %lX)\n",
+			(u_long) dump_crcaccum);
+		return(-1);
+	}
+	if (fmt_srec)
+		fputs(dumpsrec_s7_line, dump_outfile);
+	fclose(dump_outfile);
+	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);
+}