📄 gpsflash.c
字号:
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: gpsflash.c 4471 2007-12-08 08:02:57Z ckuethe $ \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: %d\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(%d)\n", ls); return 1; } if (read(lfd, loader, ls) != (ssize_t)ls) { (void)free(loader); gpsd_report(LOG_ERROR, "read(%d)\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: %d\n", fs); return 1; } /* malloc an image buffer */ if ((firmware = malloc(fs+1)) == NULL) { (void)free(loader); gpsd_report(LOG_ERROR, "malloc(%u)\n", (unsigned)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(%u)\n", (unsigned)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 boolsrec_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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -