diff loadtools/ltdump.c @ 641:b4070292640a

fc-loadtool: dump facility changed to use BINDUMP
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 01 Mar 2020 20:06:21 +0000
parents 5385aca4d813
children 141372e0d28f
line wrap: on
line diff
--- a/loadtools/ltdump.c	Sun Mar 01 18:54:29 2020 +0000
+++ b/loadtools/ltdump.c	Sun Mar 01 20:06:21 2020 +0000
@@ -4,6 +4,8 @@
  */
 
 #include <sys/types.h>
+#include <sys/time.h>
+#include <sys/errno.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
@@ -11,82 +13,81 @@
 #include <stdlib.h>
 #include <time.h>
 
-extern uint32_t crc32_table[];
+extern int errno;
 
-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_initial_time, dump_last_time;
+extern int target_fd;
+extern uint32_t crc32_table[];
 
 static char dumpsrec_s0_line[] = "S007000044554D50C2\n";
 static char dumpsrec_s7_line[] = "S70500000000FA\n";
 
-static
-dump_receiver(line)
-	char *line;
+collect_binblock_from_target(buf, expect_len, timeout)
+	u_char *buf;
+	unsigned expect_len;
 {
-	int i, b;
-	u_char sr_cksum;
-	uint32_t addr_from_srec;
-	time_t curtime;
+	fd_set fds;
+	struct timeval tv;
+	unsigned rcvd;
+	int cc;
 
-	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) {
+	for (rcvd = 0; rcvd < expect_len; ) {
+		FD_ZERO(&fds);
+		FD_SET(target_fd, &fds);
+		tv.tv_sec = timeout;
+		tv.tv_usec = 0;
+		cc = select(target_fd+1, &fds, NULL, NULL, &tv);
+		if (cc < 0) {
+			if (errno == EINTR)
+				continue;
+			perror("select");
+			return(-1);
+		}
+		if (cc < 1) {
 			fprintf(stderr,
-			"data from target: S-record hex decode error\n");
+				"error: timeout waiting for binary block\n");
+			return(-1);
+		}
+		cc = read(target_fd, buf + rcvd, expect_len - rcvd);
+		if (cc <= 0) {
+			perror("read after successful select");
 			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);
+		rcvd += cc;
 	}
-	/* 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);
+	return(0);
+}
+
+write_block_in_srec(buf, addr, blklen, outfile)
+	u_char *buf;
+	uint32_t addr;
+	unsigned blklen;
+	FILE *outfile;
+{
+	unsigned remain, reclen, n;
+	u_char binrec[38], accum;
+
+	for (remain = blklen; remain; remain -= reclen) {
+		reclen = 32;
+		if (remain < reclen)
+			reclen = remain;
+		binrec[0] = reclen + 5;
+		binrec[1] = addr >> 24;
+		binrec[2] = addr >> 16;
+		binrec[3] = addr >> 8;
+		binrec[4] = addr;
+		bcopy(buf, binrec + 5, reclen);
+		accum = 0;
+		for (n = 0; n < reclen + 5; n++)
+			accum += binrec[n];
+		binrec[n] = ~accum;
+		putc('S', outfile);
+		putc('3', outfile);
+		for (n = 0; n < reclen + 6; n++)
+			fprintf(outfile, "%02X", binrec[n]);
+		putc('\n', outfile);
+		buf += reclen;
+		addr += reclen;
 	}
-	dump_nextaddr += 0x80;
-	dump_last_time = curtime;
-	return(1);
 }
 
 loadtool_memdump(start_addr, area_len, filename, fmt_srec)
@@ -94,31 +95,26 @@
 	char *filename;
 {
 	u_long target_crc_init, target_crc_fin;
+	FILE *dump_outfile;
+	uint32_t dump_nextaddr, dump_crcaccum;
+	uint32_t dump_total_len, dump_progress_len, dump_remain;
+	unsigned blklen, n;
 	char *target_argv[4], target_arg1[10], target_arg2[10];
+	u_char recvbuf[8192], expect_blkhdr[8];
+	time_t dump_initial_time, dump_last_time, curtime;
 	unsigned duration, mm, ss;
-	int stat;
+	int rc;
 
-	if (!area_len) {
-		fprintf(stderr,
-			"error: dump of zero length is not supported\n");
-		return(-1);
-	}
-	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);
+	rc = crc32_on_target(start_addr, area_len, &target_crc_init);
+	if (rc)
+		return(rc);
 	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;
@@ -128,23 +124,71 @@
 	time(&dump_initial_time);
 	sprintf(target_arg1, "%lx", start_addr);
 	sprintf(target_arg2, "%lx", area_len);
-	target_argv[0] = "DUMP";
+	target_argv[0] = "BINDUMP";
 	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) {
+	rc = tpinterf_send_cmd();
+	if (rc < 0) {
 		fclose(dump_outfile);
-		return(stat);
+		return(rc);
 	}
-	stat = tpinterf_capture_output(2, dump_receiver);
-	if (stat < 0) {
-		fclose(dump_outfile);
-		return(stat);
+	expect_blkhdr[0] = 0x55;
+	expect_blkhdr[1] = 0xAA;
+	for (dump_remain = dump_total_len; dump_remain; dump_remain -= blklen) {
+		blklen = 8192;
+		if (dump_remain < blklen)
+			blklen = dump_remain;
+		rc = collect_binblock_from_target(recvbuf, 8, 2);
+		if (rc < 0) {
+			fclose(dump_outfile);
+			return(rc);
+		}
+		expect_blkhdr[2] = dump_nextaddr >> 24;
+		expect_blkhdr[3] = dump_nextaddr >> 16;
+		expect_blkhdr[4] = dump_nextaddr >> 8;
+		expect_blkhdr[5] = dump_nextaddr;
+		expect_blkhdr[6] = blklen >> 8;
+		expect_blkhdr[7] = blklen;
+		if (bcmp(recvbuf, expect_blkhdr, 8)) {
+			fprintf(stderr,
+				"error: expected block header mismatch\n");
+			fclose(dump_outfile);
+			return(rc);
+		}
+		rc = collect_binblock_from_target(recvbuf, blklen, 2);
+		if (rc < 0) {
+			fclose(dump_outfile);
+			return(rc);
+		}
+		/* save the bits */
+		if (fmt_srec) {
+			if (!dump_progress_len)
+				fputs(dumpsrec_s0_line, dump_outfile);
+			write_block_in_srec(recvbuf, dump_nextaddr, blklen,
+						dump_outfile);
+		} else
+			fwrite(recvbuf, 1, blklen, dump_outfile);
+		/* update running CRC */
+		for (n = 0; n < blklen; n++)
+			dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^
+							recvbuf[n]] ^
+					(dump_crcaccum >> 8);
+		/* progress indication */
+		dump_progress_len += blklen;
+		n = dump_progress_len * 100 / dump_total_len;
+		time(&curtime);
+		if (curtime != dump_last_time || n == 100) {
+			printf("\rRx %lu out of %lu bytes (%u%%)",
+				(u_long) dump_progress_len,
+				(u_long) dump_total_len, n);
+			fflush(stdout);
+		}
+		dump_nextaddr += blklen;
+		dump_last_time = curtime;
 	}
 	putchar('\n');	/* after last progress line */
-
 	/* sanity checks */
 	if (dump_nextaddr != start_addr + area_len) {
 		fclose(dump_outfile);
@@ -161,15 +205,25 @@
 	if (fmt_srec)
 		fputs(dumpsrec_s7_line, dump_outfile);
 	fclose(dump_outfile);
+
+	/* collect '=' at the end */
+	rc = collect_binblock_from_target(recvbuf, 1, 1);
+	if (rc < 0)
+		return(rc);
+	time(&dump_last_time);
+	if (recvbuf[0] != '=') {
+		fprintf(stderr, "error: \'=\' not received at the end\n");
+		return(-1);
+	}
 	duration = dump_last_time - dump_initial_time;
 	mm = duration / 60;
 	ss = duration - mm * 60;
 	printf("Dump stream received in %um%us\n", mm, ss);
 
 	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);
+	rc = crc32_on_target(start_addr, area_len, &target_crc_fin);
+	if (rc)
+		return(rc);
 	if (target_crc_fin == target_crc_init) {
 		printf("match, dump successful\n");
 		return(0);