diff options
author | Chris Kuethe <chris.kuethe@gmail.com> | 2009-06-03 22:14:23 +0000 |
---|---|---|
committer | Chris Kuethe <chris.kuethe@gmail.com> | 2009-06-03 22:14:23 +0000 |
commit | 8a7d06c58868486632f82fb75225f666999f3c63 (patch) | |
tree | 4d796107d0823589e408f30dea368a386089a472 | |
parent | b2de364fa9cfacb0138fb0ab85860a4d523cce50 (diff) | |
download | gpsd-8a7d06c58868486632f82fb75225f666999f3c63.tar.gz |
Bye-bye gpsflash.
It's unlikely that we'll ever be able to make this ready for
prime-time use without a lot more vendor assistance. If someone wants
this, they can resurrect it from the version history.
-rw-r--r-- | Makefile.am | 12 | ||||
-rw-r--r-- | gpsflash.c | 689 | ||||
-rw-r--r-- | gpsflash.h | 65 | ||||
-rw-r--r-- | gpsflash.xml | 108 | ||||
-rw-r--r-- | sirfflash.c | 337 |
5 files changed, 1 insertions, 1210 deletions
diff --git a/Makefile.am b/Makefile.am index 0bac06cd..5d181dbc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,7 +45,7 @@ RTCM104PROGS = gpsdecode RTCM104PAGES = $(RTCM104PAGES_DIST) endif -bin_PROGRAMS = $(MOTIF_PROGS) $(XAW_PROGS) $(RTCM104PROGS) $(CURSESPROGS) gpsctl gpspipe gpsflash gpxlogger lcdgps +bin_PROGRAMS = $(MOTIF_PROGS) $(XAW_PROGS) $(RTCM104PROGS) $(CURSESPROGS) gpsctl gpspipe gpxlogger lcdgps sbin_PROGRAMS = gpsd check_PROGRAMS = test_float test_bits test_gpsmm test_packet test_mkgmtime test_geoid @@ -127,12 +127,6 @@ gpsdecode_SOURCES = gpsdecode.c gpsdecode_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD) # -# Build gpsflash -# -gpsflash_SOURCES = gpsflash.c gpsflash.h sirfflash.c -gpsflash_LDADD = $(LIBM) libgps.la -lm - -# # Build shared libraries # libgps_la_LDFLAGS = -version-number 18:0:0 @@ -282,7 +276,6 @@ MANPAGES_BASE = \ gpsmon.1 \ gpsctl.1 \ gpspipe.1 \ - gpsflash.1 \ rtcm-104.5 \ srec.5 @@ -358,7 +351,6 @@ EXTRA_DIST = \ gpsdecode.xml \ rtcm-104.xml \ srec.xml \ - gpsflash.xml \ $(MANPAGES_DIST) \ xgps.ad \ xgpsspeed.ad \ @@ -417,8 +409,6 @@ splint: gpsd.h packet_names.h -splint $(SPLINTOPTS) $(gpspipe_SOURCES) @echo "Running splint on gpsdecode..." -splint $(SPLINTOPTS) -exportlocal gpsdecode.c - @echo "Running splint on gpsflash..." - -splint $(SPLINTOPTS) $(gpsflash_SOURCES) @echo "Running splint on test_bits test harness..." -splint $(SPLINTOPTS) $(test_bits_SOURCES) @echo "Running splint on test_packet test harness..." diff --git a/gpsflash.c b/gpsflash.c deleted file mode 100644 index 0defe531..00000000 --- a/gpsflash.c +++ /dev/null @@ -1,689 +0,0 @@ -/* $Id$ */ -/* - * This is the GPS-type-independent part of the gpsflash program. - * - */ -/* - * Copyright (c) 2005-2007 Chris Kuethe <chris.kuethe@gmail.com> - * Copyright (c) 2005-2007 Eric S. Raymond <esr@thyrsus.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include <stdarg.h> -#include <string.h> -#ifndef S_SPLINT_S -#include <unistd.h> -#endif /* S_SOLINT_S */ -#include "gpsd_config.h" -#include "gpsd.h" -#include "gpsflash.h" - -/* block size when writing to the serial port. related to FIFO size */ -#define WRBLK 128 - -static char *progname; -static int verbosity = 0; - -static bool srec_check(const char *data); - -void gpsd_report(int errlevel, const char *fmt, ... ) -/* assemble command in printf(3) style, use stderr or syslog */ -{ - if (errlevel <= verbosity) { - char buf[BUFSIZ]; - va_list ap; - - (void)strlcpy(buf, progname, BUFSIZ); - (void)strlcat(buf, ": ", BUFSIZ); - va_start(ap, fmt) ; - (void)vsnprintf(buf + strlen(buf), sizeof(buf)-strlen(buf), fmt, ap); - va_end(ap); - (void)fputs(buf, stdout); - } -} - -static void -usage(void){ - fprintf(stderr, "Usage: %s [-v d] [-n] [-l <loader_file>] -f <firmware_file> {<tty>}\n", progname); -} - -int -serialSpeed(int pfd, struct termios *term, int speed){ - int rv; - int r = 0; - - switch(speed){ -#ifdef B115200 - case 115200: - speed = B115200; - break; -#endif -#ifdef B57600 - case 57600: - speed = B57600; - break; -#endif - case 38400: - speed = B38400; - break; -#ifdef B28800 - case 28800: - speed = B28800; - break; -#endif - case 19200: - speed = B19200; - break; -#ifdef B14400 - case 14400: - speed = B14400; - break; -#endif - case 9600: - speed = B9600; - break; - case 4800: - speed = B9600; - break; - default: - errno = EINVAL; - return -1; - } - - /* set UART speed */ - (int)tcgetattr(pfd, term); - /*@ ignore @*/ - cfsetispeed(term, speed); - cfsetospeed(term, speed); - /*@ end @*/ - while (((rv = tcsetattr(pfd, TCSAFLUSH, term)) == -1) && \ - (errno == EINTR) && (r < 3)) { - /* retry up to 3 times on EINTR */ - (void)usleep(1000); - r++; - } - - if(rv == -1) - return -1; - else - return 0; -} - - -int -serialConfig(int pfd, struct termios *term, int speed){ - int rv; - int r = 0; - - /* get the current terminal settings */ - (void)tcgetattr(pfd, term); - /* set the port into "raw" mode. */ - /*@i@*/cfmakeraw(term); - term->c_lflag &=~ (ICANON); - /* Enable serial I/O, ignore modem lines */ - term->c_cflag |= (CLOCAL | CREAD); - /* No output postprocessing */ - term->c_oflag &=~ (OPOST); - /* 8 data bits */ - term->c_cflag |= CS8; - term->c_iflag &=~ (ISTRIP); - /* No parity */ - term->c_iflag &=~ (INPCK); - term->c_cflag &=~ (PARENB | PARODD); - /* 1 Stop bit */ - term->c_cflag &=~ (CSIZE | CSTOPB); - /* No flow control */ - term->c_iflag &=~ (IXON | IXOFF); -#if defined(CCTS_OFLOW) && defined(CRTS_IFLOW) && defined(MDMBUF) - term->c_oflag &=~ (CCTS_OFLOW | CRTS_IFLOW | MDMBUF); -#endif -#if defined(CRTSCTS) - term->c_oflag &=~ (CRTSCTS); -#endif - - /* we'd like to read back at least 2 characters in .2sec */ - /*@i@*/term->c_cc[VMIN] = 2; - /*@i@*/term->c_cc[VTIME] = 2; - - /* apply all the funky control settings */ - while (((rv = tcsetattr(pfd, TCSAFLUSH, term)) == -1) && \ - (errno == EINTR) && (r < 3)) { - /* retry up to 3 times on EINTR */ - (void)usleep(1000); - r++; - } - - if(rv == -1) - return -1; - - /* and if that all worked, try change the UART speed */ - return serialSpeed(pfd, term, speed); -} - -int -binary_send(int pfd, char *data UNUSED , size_t ls){ - unsigned char *msg; - size_t nbr, nbs, nbx; - ssize_t r; - static int count; - double start = timestamp(); - - /*@ -compdef @*/ - if((msg = malloc(ls+10)) == NULL){ - return -1; /* oops. bail out */ - } - - fprintf(stderr, "gpsflash: transferring binary... \010"); - count = 0; - - nbr = ls+10; nbs = WRBLK ; nbx = 0; - while(nbr){ - if(nbr > WRBLK ) - nbs = WRBLK ; - else - nbs = nbr; - -r0: if((r = write(pfd, msg+nbx, nbs)) == -1){ - if (errno == EAGAIN){ /* retry */ - (void)tcdrain(pfd); /* wait a moment */ - errno = 0; /* clear errno */ - nbr -= r; /* number bytes remaining */ - nbx += r; /* number bytes sent */ - goto r0; - } else { - (void)free(msg); - return -1; /* oops. bail out */ - } - } - nbr -= r; - nbx += r; - - (void)fputc("-/|\\"[count % 4], stderr); - (void)fputc('\010', stderr); - (void)fflush(stdout); - } - /*@ +compdef @*/ - - (void)fprintf(stderr, "...done (%2.2f sec).\n", timestamp()-start); - - (void)free(msg); - return 0; -} - - -int -srecord_send(int pfd, char *data, size_t len){ - int r, i; - size_t tl; - char sendbuf[85], recvbuf[8]; - static int count; - double start = timestamp(); - - /* srecord loading is interactive. send line, get reply */ - /* when sending S-records, check for SA/S5 or SE */ - - fprintf(stderr, "gpsflash: transferring S-records... \010"); - count = 0; - - memset(recvbuf, 0, 8); - i = 0; - - while(strlen(data)){ - /* grab a line of firmware, ignore line endings */ - if ((r = (int)strlen(data))){ - memset(sendbuf,0,85); - if((r = sscanf(data, "%80s", sendbuf)) == EOF) - return 0; - - tl = strlen(sendbuf); - if ((tl < 1) || (tl > 80)) - return -1; - - data += tl; - len -= tl; - - while((data[0] != 'S') && (data[0] != '\0')) - data++; - - sendbuf[tl] = '\r'; - sendbuf[tl+1] = '\n'; - tl += 2; - - if ((++i % 1000) == 0) - printf ("%6d\n", i); - - (void)tcflush(pfd, TCIFLUSH); - if((r = (int)write(pfd, sendbuf, tl+2)) != (int)tl+2) - return -1; /* oops. bail out */ - - (void)tcdrain(pfd); - if((r = (int)read(pfd, recvbuf, 7)) == -1) - return -1; /* oops. bail out */ - - if (!((recvbuf[0] == 'S') && ((recvbuf[1] == 'A') || (recvbuf[1] == '5')))) - return -1; /* oops. bail out */ - } - - (void)fputc("-/|\\"[count % 4], stderr); - (void)fputc('\010', stderr); - (void)fflush(stdout); - } - - (void)fprintf(stderr, "...done (%2.2f sec).\n", timestamp()-start); - return 0; -} - -bool -expect(int pfd, const char *str, size_t len, time_t timeout) -/* keep reading till we see a specified expect string or time out */ -{ - size_t got = 0; - char ch; - double start = timestamp(); - - gpsd_report(LOG_PROG, "expect(%s, %d)\n", - gpsd_hexdump((char *)str, len), - (int)timeout); - - for (;;) { - if (read(pfd, &ch, 1) != 1) - return false; /* I/O failed */ - gpsd_report(LOG_RAW, "I see %zd: %02x\n", got, (unsigned)(ch & 0xff)); - if (timestamp() - start > (double)timeout) - return false; /* we're timed out */ - else if (got == len) - return true; /* we're done */ - else if (ch == str[got]) - got++; /* match continues */ - else - got = 0; /* match fails, retry */ - } -} - - -#if defined(SIRF_ENABLE) && defined(BINARY_ENABLE) -/* add new types by adding pointers to their driver blocks to this list */ -/*@ -nullassign @*/ -static struct flashloader_t *types[] = {&sirf_type, NULL}; -/*@ +nullassign @*/ -#else -/* add new types by adding pointers to their driver blocks to this list */ -/*@ -nullassign @*/ -static struct flashloader_t *types[] = {NULL, NULL}; -/*@ +nullassign @*/ -#endif - -int -main(int argc, char **argv){ - - int ch; - int lfd, ffd, pfd; - size_t ls, fs; - bool fflag = false, lflag = false, nflag = false; - struct stat sb; - struct flashloader_t *gpstype, **gp; - char *fname = NULL; - char *lname = NULL; - char *port = NULL; - char *warning; - struct termios term; - sigset_t sigset; - char *firmware = NULL; - char *loader = NULL; - char *version = NULL; - - progname = argv[0]; - - while ((ch = getopt(argc, argv, "f:l:nVv:")) != -1) - switch (ch) { - case 'f': - fname = optarg; - fflag = true; - break; - case 'l': - lname = optarg; - lflag = true; - break; - case 'n': - nflag = true; - break; - case 'v': - verbosity = atoi(optarg); - break; - case 'V': - (void)fprintf(stderr, "SVN ID: $Id$ \n"); - exit(0); - default: - usage(); - exit(0); - /* NOTREACHED */ - } - - argc -= optind; - argv += optind; - - /* there is exactly one required argument, a tty device */ - if (argc == 1) - port = argv[0]; - else { - usage(); - exit(0); - } - - if (!nflag && - (((warning = getenv("I_READ_THE_WARNING")) == NULL) || - (strcmp(warning, "why oh why didn't i take the blue pill")!=0))){ - printf("\nThis program rewrites your receiver's flash ROM.\n"); - printf("If done improperly this will permanently ruin your\n"); - printf("receiver. We insist you read the gpsflash manpage\n"); - printf("before you break something.\n\n"); - nflag = true; - } - - if (!nflag) { - /* make sure we have meaningful flags */ - if (!fflag || fname == NULL) { - usage(); - return 1; - } - } - - /* Open the serial port, blocking is OK */ - if((pfd = open(port, O_RDWR | O_NOCTTY , 0600)) == -1) { - gpsd_report(LOG_ERROR, "open(%s)\n", port); - return 1; - } - - /* try to get an identification string out of the firmware */ - gpstype = NULL; - for (gp = types; *gp; gp++) { - gpstype = *gp; - gpsd_report(LOG_PROG, "probing for %s\n", gpstype->name); - if (gpstype->probe(pfd, &version) == 0) - break; - } - if (gpstype == NULL || version == NULL) { - gpsd_report(LOG_ERROR, "not a known GPS type\n"); - return 1; - } - - /* OK, we have a known type */ - gpsd_report(LOG_SHOUT, "GPS is %s, version '%s'.\n", gpstype->name, version); - if (lname == NULL) - lname = (char *)gpstype->flashloader; - - if (nflag) { - gpsd_report(LOG_PROG, "probe finished.\n"); - return 0; - } - - /* there may be a type-specific setup method */ - memset(&term, 0, sizeof(term)); - if(gpstype->port_setup(pfd, &term) == -1) { - gpsd_report(LOG_ERROR, "port_setup()\n"); - return 1; - } - - gpsd_report(LOG_PROG, "port set up...\n"); - - /* Open the loader file */ - if((lfd = open(lname, O_RDONLY, 0444)) == -1) { - gpsd_report(LOG_ERROR, "open(%s)\n", lname); - return 1; - } - - /* fstat() its file descriptor. Need the size, and avoid races */ - if(fstat(lfd, &sb) == -1) { - gpsd_report(LOG_ERROR, "fstat(%s)\n", lname); - return 1; - } - - /* minimal sanity check on loader size. also prevents bad malloc() */ - ls = (size_t)sb.st_size; - if ((ls < gpstype->min_loader_size)||(ls > gpstype->max_loader_size)){ - gpsd_report(LOG_ERROR, "preposterous loader size: %zd\n", ls); - return 1; - } - - gpsd_report(LOG_PROG, "passed sanity checks...\n"); - - /* malloc a loader buffer */ - if ((loader = malloc(ls)) == NULL) { - gpsd_report(LOG_ERROR, "malloc(%zd)\n", ls); - return 1; - } - - if (read(lfd, loader, ls) != (ssize_t)ls) { - (void)free(loader); - gpsd_report(LOG_ERROR, "read(%zd)\n", ls); - return 1; - } - - /* don't care if close fails - kernel will force close on exit() */ - (void)close(lfd); - - gpsd_report(LOG_PROG, "loader read in...\n"); - - /* Open the firmware image file */ - /*@ -nullpass @*/ - if((ffd = open(fname, O_RDONLY, 0444)) == -1) { - (void)free(loader); - gpsd_report(LOG_ERROR, "open(%s)]n", fname); - return 1; - } - if(fstat(ffd, &sb) == -1) { - (void)free(loader); - gpsd_report(LOG_ERROR, "fstat(%s)\n", fname); - return 1; - } - - /* minimal sanity check on firmware size. also prevents bad malloc() */ - fs = (size_t)sb.st_size; - if ((fs < gpstype->min_firmware_size) || (fs > gpstype->max_firmware_size)){ - (void)free(loader); - gpsd_report(LOG_ERROR, "preposterous firmware size: %zd\n", fs); - return 1; - } - - /* malloc an image buffer */ - if ((firmware = malloc(fs+1)) == NULL) { - (void)free(loader); - gpsd_report(LOG_ERROR, "malloc(%zd)\n", fs); - return 1; - } - - /* get the firmware */ - if (read(ffd, firmware, fs) != (ssize_t)fs) { - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR, "read(%zd)\n", fs); - return 1; - } - - firmware[fs] = '\0'; - - /* don't care if close fails - kernel will force close on exit() */ - (void)close(ffd); - - gpsd_report(LOG_PROG, "firmware read in...\n"); - - /* did we just read some S-records? */ - if (!((firmware[0] == 'S') && ((firmware[1] >= '0') && (firmware[1] <= '9')))){ /* srec? */ - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR, "%s: not an S-record file\n", fname); - return 1; - } - - if(gpstype->version_check(pfd, version, loader, ls, firmware, fs)==-1){ - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR, "version_check()\n"); - return 1; - } - - /* - * dlgps2.bin starts flashing when it sees valid srecords. - * validate the entire image before we flash. shooting self - * in foot is bad, mmmkay? - */ - gpsd_report(LOG_PROG, "validating firmware\n"); - if (srec_check(firmware)){ - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR, "%s: corrupted firmware image\n", fname); - return 1; - } - /*@ +nullpass @*/ - gpsd_report(LOG_PROG, "firmware validated\n"); - - gpsd_report(LOG_PROG, "version checked...\n"); - - gpsd_report(LOG_PROG, "blocking signals...\n"); - - /* once we get here, we are uninterruptable. handle signals */ - (void)sigemptyset(&sigset); - (void)sigaddset(&sigset, SIGINT); - (void)sigaddset(&sigset, SIGHUP); - (void)sigaddset(&sigset, SIGQUIT); - (void)sigaddset(&sigset, SIGTSTP); - (void)sigaddset(&sigset, SIGSTOP); - (void)sigaddset(&sigset, SIGKILL); - - if(sigprocmask(SIG_BLOCK, &sigset, NULL) == -1) { - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR,"sigprocmask\n"); - return 1; - } - - /* send the command to begin the update */ - if(gpstype->stage1_command!=NULL && (gpstype->stage1_command(pfd) == -1)) { - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR, "Stage 1 update command\n"); - return 1; - } - - gpsd_report(LOG_PROG, "sending loader...\n"); - - /* send the bootstrap/flash programmer */ - if(gpstype->loader_send(pfd, &term, loader, ls) == -1) { - (void)free(loader); - (void)free(firmware); - gpsd_report(LOG_ERROR, "Loader send\n"); - return 1; - } - (void)free(loader); - - gpsd_report(LOG_PROG, "initializing firmware load...\n"); - - /* send any command needed to demarcate the two loads */ - if(gpstype->stage2_command!=NULL && (gpstype->stage2_command(pfd) == -1)) { - (void)free(firmware); - gpsd_report(LOG_ERROR, "Stage 2 update command\n"); - return 1; - } - - gpsd_report(LOG_PROG, "performing firmware load...\n"); - - /* and now, poke the actual firmware over */ - if(gpstype->firmware_send(pfd, firmware, fs) == -1) { - (void)free(firmware); - gpsd_report(LOG_ERROR, "Firmware send\n"); - return 1; - } - (void)free(firmware); - - gpsd_report(LOG_PROG, "finishing firmware load...\n"); - - /* send any command needed to finish the firmware load */ - if(gpstype->stage3_command!=NULL && (gpstype->stage3_command(pfd) == -1)) { - gpsd_report(LOG_ERROR, "Stage 3 update command\n"); - return 1; - } - - gpsd_report(LOG_PROG, "unblocking signals...\n"); - - if(sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1) { - gpsd_report(LOG_ERROR,"sigprocmask\n"); - return 1; - } - - /* type-defined wrapup, take our tty to GPS's post-flash settings */ - if(gpstype->port_wrapup(pfd, &term) == -1) { - gpsd_report(LOG_ERROR, "port_wrapup()\n"); - return 1; - } - - gpsd_report(LOG_PROG, "finished.\n"); - - /* return() from main(), to take advantage of SSP compilers */ - return 0; -} - -static bool -srec_check(const char *data){ - int i, l, n, x, y, z; - char buf[85]; - - l = 0; - while(strlen(data)){ - /* grab a line of firmware, ignore line endings */ - memset(buf,0,85); - l++; - if(sscanf(data, "%80s", buf) == EOF){ - gpsd_report(LOG_ERROR, "line %d read failed\n", l); - return true; - } - - n = (int)strlen(buf); - if ((n < 1) || (n > 80)){ - gpsd_report(LOG_ERROR, "firmware line %d invalid length %d\n", l, n); - return true; - } - - /* advance to the next srecord */ - data += n; - while((data[0] != 'S') && (data[0] != '\0')) - data++; - - if (buf[0] != 'S'){ - gpsd_report(LOG_INF, "%s\n", buf); - gpsd_report(LOG_ERROR, "firmware line %d doesn't begin with 'S'.\n", l); - return true; - } - - x = hex2bin(buf+2); - y = (n - 4)/2; - if (x != y){ - gpsd_report(LOG_INF, "buf: '%s'\n", buf); - gpsd_report(LOG_ERROR, "firmware line %d length error: %d != %d\n", l, x, y); - return true; - } - - x = hex2bin(buf+n-2); - y = 0; - for(i = 2; i < n-2; i+=2){ - z = hex2bin(buf+i); - y += z; - } - y &= 0xff; y ^= 0xff; - if (x != y){ - gpsd_report(LOG_INF, "buf: '%s'\n", buf); - gpsd_report(LOG_ERROR, "firmware line %d checksum error: %x != %x\n", l, x, y); - return true; - } - } - return false; -} diff --git a/gpsflash.h b/gpsflash.h deleted file mode 100644 index 3e16dc0f..00000000 --- a/gpsflash.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $Id$ */ -#ifndef _GPSD_GPSFLASH_H_ -#define _GPSD_GPSFLASH_H_ - -/* - * Copyright (c) 2005 Chris Kuethe <chris.kuethe@gmail.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/stat.h> - -#ifndef S_SPLINT_S -#include <netinet/in.h> /* for htonl() under Linux */ -#endif /* S_SPLINT_S */ - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <stdbool.h> - -struct flashloader_t { - const char *name; - const char *flashloader; - size_t min_loader_size, max_loader_size; - size_t min_firmware_size, max_firmware_size; - int (*probe)(int fd, char **version); - int (*port_setup)(int fd, struct termios *term); - int (*version_check)(int fd, const char *, - const char *, size_t, - const char *, size_t); - int (*stage1_command)(int fd); - int (*loader_send)(int pfd, struct termios *term, char *loader, size_t ls); - int (*stage2_command)(int fd); - int (*firmware_send)(int pfd, char *loader, size_t ls); - int (*stage3_command)(int fd); - int (*port_wrapup)(int fd, struct termios *term); -}; -extern struct flashloader_t sirf_type; - -int serialConfig(int, struct termios *, int); -int serialSpeed(int, struct termios *, int); -int srecord_send(int pfd, char *fw, size_t len); -int binary_send(int pfd, char *data, size_t ls); -bool expect(int pfd, const char *str, size_t len, time_t timeout); - -#endif /* _GPSD_GPSFLASH_H_ */ diff --git a/gpsflash.xml b/gpsflash.xml deleted file mode 100644 index 0ece13c0..00000000 --- a/gpsflash.xml +++ /dev/null @@ -1,108 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE refentry PUBLIC - "-//OASIS//DTD DocBook XML V4.1.2//EN" - "docbook/docbookx.dtd"> -<refentry id='gpsflash.1'> -<refmeta> -<refentrytitle>gpsflash</refentrytitle> -<manvolnum>1</manvolnum> -<refmiscinfo class='date'>15 Jul 2005</refmiscinfo> -</refmeta> -<refnamediv id='name'> -<refname>gpsflash</refname> -<refpurpose>2-stage firmware loader for GPS chipsets</refpurpose> -</refnamediv> -<refsynopsisdiv id='synopsis'> - -<cmdsynopsis> - <command>gpsflash</command> - <arg choice='opt'>-n</arg> - <arg choice='opt'>-l <replaceable>loader-file</replaceable></arg> - <arg choice='plain'>-f <replaceable>firmware-file</replaceable></arg> - <arg choice='req'><replaceable>tty</replaceable></arg> -</cmdsynopsis> -</refsynopsisdiv> - -<refsect1 id='description'><title>DESCRIPTION</title> - -<para>This program is a firmware loader for GPSes connected to your -host computer via serial or USB port. Presently it supports only SiRF -GPSes. Other GPSes may be supported in the future if the vendors -cooperate.</para> - -<para>For operation, this program requires a flashloader binary (found -by default in a file named <filename>dlgsp2.bin</filename>) and a -firmware image. This program first ships a command that tells the GPS -a flashloader image will follow, then gives the GPS time to reboot into the -flashloader. The flashloader then accepts S-records from the serial -or USB port until it sees a termination record, at which point it -writes the new firmware into the GPS's non-volatile memory -and reboots the chip into the new firmware.</para> - -<para>There is one required argument, specifying the serial device to -which the GPS is connected.</para> - -<para>The -l option specifies the flashloader binary. The -f option -specifies the firmware image file, and is required unless you -are just probing the GPS (-n option).</para> - -<para>If the -n option is specified, the program will probe the -GPS to try to determine its type and whether the upload is -compatible, but not actually perform the upload. When this option -is specified, the -f option is not required.</para> - -<para>You will need to obtain your own copy of -<filename>dlgsp2.bin</filename> and your own firmware image. The GPSD -project does not yet have permission to distribute these files, so -don't ask us for copies.</para> - -<para>Depending on your GPS type, this program may or may not attempt -to check that the flashloader or firmware image is compatible with -your GPS; in some cases no check is possible. <emphasis -role='strong'>EXPERIMENT AT YOUR OWN RISK.</emphasis> -</para> - -<para>This program will only work with firmware images in S-record -format, which is the form SiRF normally distributes them in. If you -get a binary firmware image from somewhere, you can use -<citerefentry><refentrytitle>objdump</refentrytitle><manvolnum>1</manvolnum></citerefentry>, -from the GNU binutils to convert it to S-records.</para> - -<para>Realize that we are not kidding around when we say that this -could very well break your receiver permanently, and if it does, it's -no one's fault but your own. For this program to flash your GPS, you must set -an environment variable called I_READ_THE_WARNING with the value "why -oh why didn't i take the blue pill".</para> - -<para>This program emits progress messages to standard output.</para> - -<para>The GPS will be reset to 4800bps NMEA after flash.</para> - -</refsect1> -<refsect1 id='bugs'><title>BUGS AND LIMITAIONS</title> - -<warning><para>THIS PROGRAM CAN DESTROY YOUR GPS. A botched firmware upload -will turn it into a paperweight. USE AT YOUR OWN RISK. Maintainers -are not responsible for direct or incidental damages. YOU HAVE BEEN -WARNED.</para></warning> - -</refsect1> -<refsect1 id='see_also'><title>SEE ALSO</title> -<para> -<citerefentry><refentrytitle>gpsd</refentrytitle><manvolnum>8</manvolnum></citerefentry>, -<citerefentry><refentrytitle>gps</refentrytitle><manvolnum>1</manvolnum></citerefentry>, -<citerefentry><refentrytitle>libgps</refentrytitle><manvolnum>3</manvolnum></citerefentry>, -<citerefentry><refentrytitle>libgpsd</refentrytitle><manvolnum>3</manvolnum></citerefentry>, -<citerefentry><refentrytitle>srec</refentrytitle><manvolnum>5</manvolnum></citerefentry>. -</para> -</refsect1> - -<refsect1 id='maintainer'><title>AUTHOR</title> - -<para>Chris Kuethe <email>chris.kuethe@gmail.com</email>. There is a -project page for <application>gpsd</application> <ulink -url="http://gpsd.berlios.de/">here</ulink>.</para> - -</refsect1> - -</refentry> diff --git a/sirfflash.c b/sirfflash.c deleted file mode 100644 index afe505a4..00000000 --- a/sirfflash.c +++ /dev/null @@ -1,337 +0,0 @@ -/* $Id$ */ -/* - * Copyright (c) 2005-2007 Chris Kuethe <chris.kuethe@gmail.com> - * Copyright (c) 2005-2007 Eric S. Raymond <esr@thyrsus.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/* - * This is the SiRF-dependent part of the gpsflash program. - * - * If we ever compose our own S-records, dlgsp2.bin looks for this header - * unsigned char hdr[] = "S00600004844521B\r\n"; - * - * Here's what Carl Carter at SiRF told us when he sent us informattion - * on how to build one of these: - * - * -------------------------------------------------------------------------- - * Regarding programming the flash, I will attach 2 things for you -- a - * program called SiRFProg, the source for an older flash programming - * utility, and a description of the ROM operation. Note that while the - * ROM description document is for SiRFstarIII, the interface applies to - * SiRFstarII systems like you are using. Here is a little guide to how - * things work: - * - * 1. The receiver is put into "internal boot" mode -- this means that it - * is running off the code contained in the internal ROM rather than the - * external flash. You do this by either putting a pull-up resistor on - * data line 0 and cycling power or by giving a message ID 148. - * 2. The internal ROM provides a very primitive boot loader that permits - * you to load a program into RAM and then switch to it. - * 3. The program in RAM is used to handle the erasing and programming - * chores, so theoretically you could create any program of your own - * choosing to handle things. SiRFProg gives you an example of how to do - * it using Motorola S record files as the programming source. The program - * that resides on the programming host handles sending down the RAM - * program, then communicating with it to transfer the data to program. - * 4. Once the programming is complete, you transfer to it by switching to - * "external boot" mode -- generally this requires a pull-down resistor on - * data line 0 and either a power cycle or toggling the reset line low then - * back high. There is no command that does this. - * - * Our standard utility operates much faster than SiRFProg by using a - * couple tricks. One, it transfers a binary image rather than S records - * (which are ASCII and about 3x the size of the image). Two, it - * compresses the binary image using some standard compression algorithm. - * Three, when transferring the file we boost the port baud rate. Normally - * we use 115200 baud as that is all the drivers in most receivers handle. - * But when supported, we can boost up to 900 kbaud. Programming at 38400 - * takes a couple minutes. At 115200 it takes usually under 30 seconds. - * At 900 k it takes about 6 seconds. - * -------------------------------------------------------------------------- - * - * Copyright (c) 2005 Chris Kuethe <chris.kuethe@gmail.com> - */ - -#include <sys/types.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> -#include "gpsd_config.h" -#include "gpsd.h" -#include "gpsflash.h" - -#if defined(SIRF_ENABLE) && defined(BINARY_ENABLE) - -/* From the SiRF protocol manual... may as well be consistent */ -#define PROTO_SIRF 0 -#define PROTO_NMEA 1 - -#define BOOST_38400 0 -#define BOOST_57600 1 -#define BOOST_115200 2 - -static void -nmea_lowlevel_send(int fd, const char *fmt, ... ) -/* ship a command to the GPS, adding * and correct checksum */ -{ - /*@ -compdef @*/ - char buf[BUFSIZ]; - va_list ap; - size_t l; - - va_start(ap, fmt) ; -#ifdef HAVE_VSNPRINTF - (void)vsnprintf(buf + strlen(buf), sizeof(buf)-strlen(buf), fmt, ap); -#else - (void)vsprintf(buf + strlen(buf), fmt, ap); -#endif - va_end(ap); - strncat(buf, "*", 1); - nmea_add_checksum(buf + 1); - l = strlen(buf); - if (write(fd, buf, l) != (ssize_t)l) - (void)fputs("sirfflash: write to device failed\n", stderr); - /*@ +compdef @*/ -} - -static int -sirfSendUpdateCmd(int pfd){ - bool status; - /*@ +charint @*/ - static unsigned char msg[] = { - 0xa0,0xa2, /* header */ - 0x00,0x01, /* message length */ - 0x94, /* 0x94: firmware update */ - 0x00,0x00, /* checksum */ - 0xb0,0xb3}; /* trailer */ - /*@ -charint @*/ - status = sirf_write(pfd, msg); - /* wait a moment for the receiver to switch to boot rom */ - (void)sleep(2); - return status ? 0 : -1; -} - -static int -sirfSendLoader(int pfd, struct termios *term, char *loader, size_t ls){ - unsigned int x; - int r, speed = 38400; - /*@i@*/unsigned char boost[] = {'S', BOOST_38400}; - unsigned char *msg; - - if((msg = malloc(ls+10)) == NULL){ - return -1; /* oops. bail out */ - } - - /*@ +charint @*/ -#ifdef B115200 - speed = 115200; - boost[1] = BOOST_115200; -#else -#ifdef B57600 - speed = 57600; - boost[1] = BOOST_57600; -#endif -#endif - /*@ -charint @*/ - - x = (unsigned)htonl(ls); - msg[0] = 'S'; - msg[1] = (unsigned char)0; - memcpy(msg+2, &x, 4); /* length */ - memcpy(msg+6, loader, ls); /* loader */ - memset(msg+6+ls, 0, 4); /* reset vector */ - - /* send the command to jack up the speed */ - if((r = (int)write(pfd, boost, 2)) != 2) { - free(msg); - return -1; /* oops. bail out */ - } - - /* wait for the serial speed change to take effect */ - (void)tcdrain(pfd); - (void)usleep(1000); - - /* now set up the serial port at this higher speed */ - (void)serialSpeed(pfd, term, speed); - - /* ship the actual data */ - r = binary_send(pfd, (char *)msg, ls+10); - free(msg); - return r; -} - -static int -sirfSetProto(int pfd, struct termios *term, unsigned int speed, unsigned int proto){ - int i; - int spd[8] = {115200, 57600, 38400, 28800, 19200, 14400, 9600, 4800}; - /*@ +charint @*/ - static unsigned char sirf[] = { - 0xa0,0xa2, /* header */ - 0x00,0x31, /* message length */ - 0xa5, /* message 0xa5: UART config */ - 0x00,0,0, 0,0,0,0, 8,1,0, 0,0, /* port 0 */ - 0xff,0,0, 0,0,0,0, 0,0,0, 0,0, /* port 1 */ - 0xff,0,0, 0,0,0,0, 0,0,0, 0,0, /* port 2 */ - 0xff,0,0, 0,0,0,0, 0,0,0, 0,0, /* port 3 */ - 0x00,0x00, /* checksum */ - 0xb0,0xb3}; /* trailer */ - /*@ -charint @*/ - - if (serialConfig(pfd, term, 38400) == -1) - return -1; - - sirf[7] = sirf[6] = (unsigned char)proto; - /*@i@*/i = htonl(speed); /* borrow "i" to put speed into proper byte order */ - /*@i@*/bcopy(&i, sirf+8, 4); - - /* send at whatever baud we're currently using */ - (void)sirf_write(pfd, sirf); - nmea_lowlevel_send(pfd, "$PSRF100,%u,%u,8,1,0", speed, proto); - - /* now spam the receiver with the config messages */ - for(i = 0; i < (int)(sizeof(spd)/sizeof(spd[0])); i++) { - (void)serialSpeed(pfd, term, spd[i]); - (void)sirf_write(pfd, sirf); - nmea_lowlevel_send(pfd, "$PSRF100,%u,%u,8,1,0", speed, proto); - (void)tcdrain(pfd); - (void)usleep(100000); - } - - (void)serialSpeed(pfd, term, (int)speed); - (void)tcflush(pfd, TCIOFLUSH); - - return 0; -} - -/*@ -nullstate @*/ -static int sirfProbe(int fd, char **version) -/* try to elicit a return packet with the firmware version in it */ -{ - /*@ +charint @*/ - static unsigned char versionprobe[] = { - 0xa0, 0xa2, 0x00, 0x02, - 0x84, 0x00, - 0x00, 0x84, 0xb0, 0xb3}; - /*@ -charint @*/ - char buf[MAX_PACKET_LENGTH]; - ssize_t status, want; - - gpsd_report(LOG_PROG, "probing with %s\n", - gpsd_hexdump(versionprobe, sizeof(versionprobe))); - if ((status = write(fd, versionprobe, sizeof(versionprobe))) != 10) - return -1; - /* - * Older SiRF chips had a 21-character version message. Newer - * ones (GSW 2.3.2 or later) have an 81-character version message. - * Accept either. - */ - want = 0; - if (expect(fd,"\xa0\xa2\x00\x15\x06", 5, 1)) - want = 21; - else if (expect(fd,"\xa0\xa2\x00\x51\x06", 5, 1)) - want = 81; - - if (want) { - ssize_t len; - memset(buf, 0, sizeof(buf)); - for (len = 0; len < want; len += status) { - status = read(fd, buf+len, sizeof(buf)); - if (status == -1) - return -1; - } - gpsd_report(LOG_PROG, "%zd bytes = %s\n", len, gpsd_hexdump(buf, (size_t)len)); - *version = strdup(buf); - return 0; - } else { - *version = NULL; - return -1; - } -} -/*@ +nullstate @*/ - -static int sirfPortSetup(int fd, struct termios *term) -{ - /* the firware upload defaults to 38k4, so let's go there */ - return sirfSetProto(fd, term, PROTO_SIRF, 38400); -} - -static int sirfVersionCheck(int fd UNUSED, const char *version UNUSED, - const char *loader UNUSED, size_t ls UNUSED, - const char *firmware UNUSED, size_t fs UNUSED) -{ - /* - * This implies that any SiRF loader and firmware image is good for - * any SiRF chip. We really want to do more checking here... - */ - return 0; -} - -static int wait2seconds(int fd UNUSED) -{ - /* again we wait, this time for our uploaded code to start running */ - gpsd_report(LOG_PROG, "waiting 2 seconds...\n"); - return (int)sleep(2); -} - -static int wait5seconds(int fd UNUSED) -{ - /* wait for firmware upload to settle in */ - gpsd_report(LOG_PROG, "waiting 5 seconds...\n"); - return (int)sleep(5); -} - -static int sirfPortWrapup(int fd, struct termios *term) -{ - /* waitaminnit, and drop back to NMEA@4800 for luser apps */ - return sirfSetProto(fd, term, PROTO_NMEA, 4800); -} - -struct flashloader_t sirf_type = { - .name = "SiRF binary", - - /* name of default flashloader */ - .flashloader = "dlgsp2.bin", - /* - * I can't imagine a GPS firmware less than 256KB / 2Mbit. The - * latest build that I have (2.3.2) is 296KB. So 256KB is probably - * low enough to allow really old firmwares to load. - * - * As far as I know, USB receivers have 512KB / 4Mbit of - * flash. Application note APNT00016 (Alternate Flash Programming - * Algorithms) says that the S2AR reference design supports 4, 8 - * or 16 Mbit flash memories, but with current firmwares not even - * using 60% of a 4Mbit flash on a commercial receiver, I'm not - * going to stress over loading huge images. The define below is - * 524288 bytes, but that blows up nearly 3 times as S-records. - * 928K srec -> 296K binary - */ - .min_firmware_size = 262144, - .max_firmware_size = 1572864, - - /* a reasonable loader is probably 15K - 20K */ - .min_loader_size = 15440, - .max_loader_size = 20480, - - /* the command methods */ - .probe = sirfProbe, - .port_setup = sirfPortSetup, /* before signal blocking */ - .version_check = sirfVersionCheck, - .stage1_command = sirfSendUpdateCmd, - .loader_send = sirfSendLoader, - .stage2_command = wait2seconds, - .firmware_send = srecord_send, - .stage3_command = wait5seconds, - .port_wrapup = sirfPortWrapup, /* after signals unblock */ -}; -#endif /* defined(SIRF_ENABLE) && defined(BINARY_ENABLE) */ |