FreeCalypso > hg > fc-tourmaline
changeset 9:1fb47f5b597a
helpers: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 07:01:13 +0000 |
parents | 99ae5bf8cab5 |
children | 775dba605f33 |
files | .hgignore helpers/Makefile helpers/build-date.c helpers/cfg-hdr-gen.c helpers/makeline.c helpers/mk-flash-script.c helpers/mokosrec2bin.c helpers/srec4ram.c helpers/str2ind-ver.c |
diffstat | 9 files changed, 829 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,11 @@ +syntax: regexp + +^build- + +^helpers/build-date$ +^helpers/cfg-hdr-gen$ +^helpers/makeline$ +^helpers/mk-flash-script$ +^helpers/mokosrec2bin$ +^helpers/srec4ram$ +^helpers/str2ind-ver$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/Makefile Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,30 @@ +CC= gcc +CFLAGS= -O2 +PROGS= build-date cfg-hdr-gen makeline mk-flash-script mokosrec2bin srec4ram \ + str2ind-ver + +all: ${PROGS} + +build-date: build-date.c + ${CC} ${CFLAGS} -o $@ $@.c + +cfg-hdr-gen: cfg-hdr-gen.c + ${CC} ${CFLAGS} -o $@ $@.c + +makeline: makeline.c + ${CC} ${CFLAGS} -o $@ $@.c + +mk-flash-script: mk-flash-script.c + ${CC} ${CFLAGS} -o $@ $@.c + +mokosrec2bin: mokosrec2bin.c + ${CC} ${CFLAGS} -o $@ $@.c + +srec4ram: srec4ram.c + ${CC} ${CFLAGS} -o $@ $@.c + +str2ind-ver: str2ind-ver.c + ${CC} ${CFLAGS} -o $@ $@.c + +clean: + rm -f ${PROGS}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/build-date.c Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,37 @@ +/* + * This program runs at firmware build time to produce a C file for the + * fw build that includes the build date and time stamp. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <time.h> + +main(argc, argv) + char **argv; +{ + time_t now; + struct tm *tm; + + if (argc < 2 || argc > 4) { + fprintf(stderr, + "usage: %s config_name target_name src_version\n", + argv[0]); + exit(1); + } + time(&now); + tm = gmtime(&now); + printf("const char firmware_version_str[] =\n"); + if (argc >= 3) + printf("\"FreeCalypso Magnetite %s (%s), ", argv[1], argv[2]); + else + printf("\"FreeCalypso Magnetite %s, ", argv[1]); + if (argc >= 4 && strcmp(argv[3], "unknown")) + printf("source version %s, ", argv[3]); + printf("build date %d-%02d-%02dT%02d:%02d:%02dZ\";\n", + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/cfg-hdr-gen.c Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,141 @@ +/* + * This helper program generates the set of *.cfg header files, based on a + * template file and environment variables for the non-constant settings. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> + +char *infname; +FILE *inf, *outf; +char include_guard_symbol[32]; +char linebuf[256]; +int lineno; + +make_include_guard_symbol(fname) + char *fname; +{ + char *sp, *dp; + int c; + + sp = fname; + dp = include_guard_symbol; + *dp++ = '_'; + *dp++ = '_'; + while (c = *sp++) { + if (islower(c)) + c = toupper(c); + else if (c == '.') + c = '_'; + *dp++ = c; + } + *dp++ = '_'; + *dp++ = '_'; + *dp = '\0'; +} + +close_output() +{ + if (outf) { + fprintf(outf, "#endif /* %s */\n", include_guard_symbol); + fclose(outf); + outf = 0; + } +} + +bracket_line() +{ + char *cp; + + close_output(); + cp = index(linebuf+1, ']'); + if (!cp) { + fprintf(stderr, "%s line %d: unterminated bracket line\n", + infname, lineno); + exit(1); + } + *cp = '\0'; + outf = fopen(linebuf+1, "w"); + if (!outf) { + perror(linebuf+1); + exit(1); + } + make_include_guard_symbol(linebuf+1); + fprintf(outf, "#ifndef %s\n", include_guard_symbol); + fprintf(outf, "#define %s\n", include_guard_symbol); +} + +process_line() +{ + char *cp, *symbol, *value; + + if (linebuf[0] == '[') + return bracket_line(); + for (cp = linebuf; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + return; + for (symbol = cp; *cp && !isspace(*cp); cp++) + ; + if (!*cp) { +inv: fprintf(stderr, "%s line %d: expected two fields\n", + infname, lineno); + exit(1); + } + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + goto inv; + for (value = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv; + if (!strcmp(value, "var")) { + value = getenv(symbol); + if (!value) { + fprintf(stderr, + "%s line %d: no environment variable named %s\n", + infname, lineno, symbol); + exit(1); + } + } + if (!outf) { + fprintf(stderr, "%s line %d: no open output file\n", + infname, lineno); + exit(1); + } + fprintf(outf, "#define %s %s\n", symbol, value); +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s template-file output-dir\n", + argv[0]); + exit(1); + } + infname = argv[1]; + inf = fopen(infname, "r"); + if (!inf) { + perror(infname); + exit(1); + } + if (chdir(argv[2]) < 0) { + perror(argv[2]); + exit(1); + } + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) + process_line(); + close_output(); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/makeline.c Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,76 @@ +/* + * This helper utility for the FreeCalypso Magnetite build system + * emits potentially long generated Makefile lines, breaking them into + * multiple lines with backslashes. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +int is_cmd, equ_or_colon, extra_indent; +int linelen; + +main(argc, argv) + char **argv; +{ + char **ap; + + if (argc < 4) { + fprintf(stderr, "error: too few arguments\n", argv[0]); + exit(1); + } + if (!strcmp(argv[1], "def")) { + is_cmd = 0; + equ_or_colon = '='; + extra_indent = 0; + } else if (!strcmp(argv[1], "dep")) { + is_cmd = 0; + equ_or_colon = ':'; + extra_indent = 1; + } else if (!strcmp(argv[1], "cmd")) { + is_cmd = 1; + extra_indent = 1; + } else { + fprintf(stderr, "error: line type \"%s\" not known\n", argv[1]); + exit(1); + } + if (is_cmd) { + putchar('\t'); + linelen = 8; + } else + linelen = 0; + fputs(argv[2], stdout); + linelen += strlen(argv[2]); + if (is_cmd) { + putchar(' '); + linelen++; + } else { + putchar(equ_or_colon); + linelen++; + putchar('\t'); + do + linelen++; + while (linelen & 7); + } + fputs(argv[3], stdout); + linelen += strlen(argv[3]); + for (ap = argv + 4; *ap; ap++) { + if (linelen + 1 + strlen(*ap) <= 78) { + putchar(' '); + linelen++; + } else { + fputs(" \\\n\t", stdout); + linelen = 8; + if (extra_indent) { + fputs(" ", stdout); + linelen += 4; + } + } + fputs(*ap, stdout); + linelen += strlen(*ap); + } + putchar('\n'); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/mk-flash-script.c Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,39 @@ +/* + * This helper program generates the fc-loadtool command script + * for flashing the just-built firmware image. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +main(argc, argv) + char **argv; +{ + struct stat st; + u_long image_size, sector_size; + + if (argc != 4) { + fprintf(stderr, + "usage: %s fwimage.bin flash-base flash-sector-size\n", + argv[0]); + exit(1); + } + if (stat(argv[1], &st) < 0) { + perror(argv[1]); + exit(1); + } + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "error: %s is not a regular file\n", argv[1]); + exit(1); + } + image_size = st.st_size; + sector_size = strtoul(argv[3], 0, 16); + image_size += sector_size - 1; + image_size &= ~(sector_size - 1); + printf("flash erase %s 0x%lx\n", argv[2], image_size); + printf("flash program-bin %s %s\n", argv[2], argv[1]); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/mokosrec2bin.c Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,231 @@ +/* + * GSM device firmwares that are built with TI's TMS470 toolchain in TI's + * canonical way come out in TI's *.m0 format produced by TI's hex470 tool. + * TI's *.m0 is a variant of the classic S-record format from Motorola, + * but the specific variant depends on the -memwidth and -romwidth options + * with which the hex470 tool is run. + * + * In TI's canonical architecture (as opposed to Mot/Compal's heavily modified + * version) this hex470 tool is run with -memwidth 16 -romwidth 16 options, + * and the *.m0 file comes out in the format variant which we have nicknamed + * "moko-style" after its most famous user. This variant is a byte-reversed + * S-record format in that each 16-bit word is byte-reversed relative to the + * native byte order of the ARM7 processor. (This strange byte order actually + * makes some sense if one views the image as a long array of 16-bit hex + * values; 16 bits is the width of the flash memory on Calypso GSM devices and + * thus the natural unit size for flash programming.) + * + * The present mokosrec2bin utility converts these "moko-style" S-record files + * to straight binary, a conversion that includes flipping the order of bytes. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> + +char *infname; +FILE *inf, *outf; +u_char fillbyte; +char srecbuf[80]; +u_char srecbin[40]; +int lineno, state; +u_long lastaddr; + +u_char header[6] = {0x06, 0x00, 0x00, 'H', 'D', 'R'}; + +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); +} + +main(argc, argv) + char **argv; +{ + register int i; + u_long curaddr; + int datalen; + + if (argc < 3 || argc > 4) { +usage: fprintf(stderr, "usage: %s input.m0 output.bin [fill-byte]\n", + argv[0]); + exit(1); + } + infname = argv[1]; + inf = fopen(infname, "r"); + if (!inf) { + perror(infname); + exit(1); + } + if (argc > 3) { + i = decode_hex_byte(argv[3]); + if (i >= 0) + fillbyte = i; + else + goto usage; + } else + fillbyte = 0xFF; + + state = 0; + 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); + } + switch (srecbuf[1]) { + case '0': + if (state == 0) + break; + else + goto badtype; + case '3': + if (state == 0) + goto badtype; + else + break; + case '7': + if (state == 2) + break; + else + goto badtype; + default: + badtype: + fprintf(stderr, + "%s line %d: S-record type unexpected\n", + infname, lineno); + exit(1); + } + srec2bin(); + srec_cksum(); + if (state == 0) { + if (bcmp(srecbin, header, 6)) { + fprintf(stderr, "%s: expected header missing\n", + infname); + exit(1); + } + state = 1; + continue; + } + switch (srecbuf[1]) { + case '3': + if (srecbin[0] < 6) { + fprintf(stderr, + "%s line %d: S3 record is too short\n", + infname, lineno); + exit(1); + } + curaddr = (srecbin[1] << 24) | (srecbin[2] << 16) | + (srecbin[3] << 8) | srecbin[4]; + if (curaddr & 1) { + fprintf(stderr, "%s line %d: odd address\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); + } + if (state < 2) { + outf = fopen(argv[2], "w"); + if (!outf) { + perror(argv[2]); + exit(1); + } + state = 2; + lastaddr = 0; + } + if (curaddr < lastaddr) { + fprintf(stderr, + "%s line %d: address going backwards\n", + infname, lineno); + exit(1); + } + while (lastaddr < curaddr) { + putc(fillbyte, outf); + lastaddr++; + } + for (i = 0; i < datalen; i += 2) { + putc(srecbin[i + 6], outf); + putc(srecbin[i + 5], outf); + } + lastaddr = curaddr + datalen; + continue; + case '7': + fclose(outf); + exit(0); + default: + abort(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/srec4ram.c Fri Oct 16 07:01:13 2020 +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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helpers/str2ind-ver.c Fri Oct 16 07:01:13 2020 +0000 @@ -0,0 +1,42 @@ +/* + * This utility extracts the timestamp from a str2ind.tab file + * and emits the corresponding char *str2ind_version C line. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +main(argc, argv) + char **argv; +{ + FILE *inf; + char buf[32], *cp; + + if (argc != 2) { + fprintf(stderr, "usage: %s str2ind.tab\n", argv[0]); + exit(1); + } + inf = fopen(argv[1], "r"); + if (!inf) { + perror(argv[1]); + exit(1); + } + if (!fgets(buf, sizeof buf, inf)) { +inv: fprintf(stderr, + "Error: %s does not have the expected first line\n", + argv[1]); + exit(1); + } + cp = index(buf, '\n'); + if (!cp || cp == buf) + goto inv; + *cp = '\0'; + if (cp[-1] == '\r') + *--cp = '\0'; + if (cp != buf + 10) + goto inv; + printf("char *str2ind_version = \"&%s\";\n", buf); + exit(0); +}