FreeCalypso > hg > fc-magnetite
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); +}