diff helpers/srec4ram.c @ 92:40b08f6cb2b8

srec4ram helper utility written
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 02 Oct 2016 19:32:00 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/helpers/srec4ram.c	Sun Oct 02 19:32:00 2016 +0000
@@ -0,0 +1,222 @@
+/*
+ * This ad hoc utility is used as part of building RAM-loadable
+ * firmware images for targets with large RAM.  It reads the ramimage.m0
+ * S-record file produced by TI's hex470 post-linker and re-emits it
+ * in another SREC form that is suitable for feeding to fc-xram.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+char *infname;
+FILE *inf, *outf;
+char srecbuf[80];
+u_char srecbin[40], srecout[40];
+int lineno;
+
+decode_hex_byte(s)
+	char *s;
+{
+	register int u, l;
+
+	if (!isxdigit(s[0]) || !isxdigit(s[1]))
+		return(-1);
+	if (isdigit(s[0]))
+		u = s[0] - '0';
+	else if (isupper(s[0]))
+		u = s[0] - 'A' + 10;
+	else
+		u = s[0] - 'a' + 10;
+	if (isdigit(s[1]))
+		l = s[1] - '0';
+	else if (isupper(s[1]))
+		l = s[1] - 'A' + 10;
+	else
+		l = s[1] - 'a' + 10;
+	return((u << 4) | l);
+}
+
+srec2bin()
+{
+	register int i, l, b;
+
+	l = decode_hex_byte(srecbuf + 2);
+	if (l < 1) {
+		fprintf(stderr, "%s line %d: S-record length octet is bad\n",
+			infname, lineno);
+		exit(1);
+	}
+	srecbin[0] = l;
+	if (l > 35) {
+		fprintf(stderr,
+			"%s line %d: S-record is longer than expected\n",
+			infname, lineno);
+		exit(1);
+	}
+	for (i = 1; i <= l; i++) {
+		b = decode_hex_byte(srecbuf + i*2 + 2);
+		if (b < 0) {
+			fprintf(stderr, "%s line %d: hex decode error\n",
+				infname, lineno);
+			exit(1);
+		}
+		srecbin[i] = b;
+	}
+	return(0);
+}
+
+srec_cksum()
+{
+	u_char accum;
+	register int i, len;
+
+	len = srecbin[0] + 1;
+	accum = 0;
+	for (i = 0; i < len; i++)
+		accum += srecbin[i];
+	if (accum != 0xFF) {
+		fprintf(stderr, "%s line %d: bad checksum\n", infname, lineno);
+		exit(1);
+	}
+	return(0);
+}
+
+emit_output_srec(type, buf)
+	u_char *buf;
+{
+	int i;
+	u_char accum = 0;
+
+	putc('S', outf);
+	putc(type, outf);
+	for (i = 0; i < buf[0]; i++) {
+		fprintf(outf, "%02X", buf[i]);
+		accum += buf[i];
+	}
+	fprintf(outf, "%02X\n", ~accum & 0xFF);
+	return 0;
+}
+
+transform_s3()
+{
+	int datalen;
+	u_char *sp, *dp;
+	int i;
+
+	if (srecbin[0] < 6) {
+		fprintf(stderr,
+			"%s line %d: S3 record is too short\n",
+			infname, lineno);
+		exit(1);
+	}
+	datalen = srecbin[0] - 5;
+	if (datalen & 1) {
+		fprintf(stderr, "%s line %d: odd data length\n",
+			infname, lineno);
+		exit(1);
+	}
+	sp = srecbin;
+	dp = srecout;
+	for (i = 0; i < 5; i++)
+		*dp++ = *sp++;
+	for (i = 0; i < datalen; i += 2) {
+		dp[0] = sp[1];
+		dp[1] = sp[0];
+		sp += 2;
+		dp += 2;
+	}
+	return 0;
+}
+
+generate_vectors_record()
+{
+	u_char *dp;
+	u_long addr;
+	int i;
+
+	srecout[0] = 28 + 5;
+	srecout[1] = 0x00;
+	srecout[2] = 0x80;
+	srecout[3] = 0x00;
+	srecout[4] = 0x00;
+	dp = srecout + 5;
+	for (i = 0; i < 7; i++) {
+		addr = 0x01004000 + i * 4;
+		*dp++ = addr;
+		*dp++ = addr >> 8;
+		*dp++ = addr >> 16;
+		*dp++ = addr >> 24;
+	}
+	emit_output_srec('3', srecout);
+	return 0;
+}
+
+generate_jump_record()
+{
+	srecout[0] = 5;
+	srecout[1] = 0x01;
+	srecout[2] = 0x00;
+	srecout[3] = 0x40;
+	srecout[4] = 0x58;
+	emit_output_srec('7', srecout);
+	return 0;
+}
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "usage: %s input.m0 [output.srec]\n", argv[0]);
+		exit(1);
+	}
+	infname = argv[1];
+	inf = fopen(infname, "r");
+	if (!inf) {
+		perror(infname);
+		exit(1);
+	}
+	if (argc > 2) {
+		outf = fopen(argv[2], "w");
+		if (!outf) {
+			perror(argv[2]);
+			exit(1);
+		}
+	} else
+		outf = stdout;
+	for (lineno = 1; ; lineno++) {
+		if (!fgets(srecbuf, sizeof srecbuf, inf)) {
+			fprintf(stderr, "%s: premature EOF\n", infname);
+			exit(1);
+		}
+		if (srecbuf[0] != 'S') {
+			fprintf(stderr, "%s line %d: not an S-record\n",
+				infname, lineno);
+			exit(1);
+		}
+		srec2bin();
+		srec_cksum();
+		switch (srecbuf[1]) {
+		case '0':
+			emit_output_srec('0', srecbin);
+			continue;
+		case '3':
+			transform_s3();
+			emit_output_srec('3', srecout);
+			continue;
+		case '7':
+			break;
+		default:
+			fprintf(stderr, "%s line %d: unexpected S%c record\n",
+				infname, lineno, srecbuf[1]);
+			exit(1);
+		}
+		break;
+	}
+	generate_vectors_record();
+	generate_jump_record();
+	exit(0);
+}