/* $NetBSD: installboot.c,v 1.6 2017/02/12 18:21:50 maxv Exp $ */ #include #include #include #include #include #include #include "../elf2bb/chksum.h" /* XXX Must be kept in sync with bbstart.s! */ #define CMDLN_LOC 0x10 #define CMDLN_LEN 0x20 int main(int argc, char *argv[]); int main(int argc, char *argv[]){ char *line = NULL; char *progname; char *bootnam, *devnam; char *dline; int bootfd, devfd; int rc; /* read, write */ int c; /* getopt */ int sumlen; u_int32_t sum2, sum16; u_int32_t block[128*16]; progname = argv[0]; while ((c = getopt(argc, argv, "l:")) != -1) { switch(c) { case 'l': line = optarg; break; default: errx(1, "usage: %s [-l newcommandline] bootblock device", progname); } } argc -= optind; argv += optind; if (argc != 2) { errx(1, "usage: %s [-l newcommandline] bootblock device", progname); /* NOTREACHED */ } bootnam = *argv++; devnam = *argv; bootfd = open(bootnam, O_RDONLY, 0); if (bootfd < 0) { err(1, "Can't open bootblock for reading"); /* NOTREACHED */ } devfd = open(devnam, O_CREAT|O_RDWR, 0666); if (devfd < 0) { err(1, "Can't open output device for writing"); /* NOTREACHED */ } rc = read(bootfd, block, sizeof(block)); if (rc < sizeof(block)) { err(1, "Can't read bootblock"); /* NOTREACHED */ } /* XXX the choices should not be hardcoded */ sum2 = chksum(block, 1024/4); sum16 = chksum(block, 8192/4); if (sum16 == 0xffffffff) { sumlen = 8192/4; } else if (sum2 == 0xffffffff) { sumlen = 1024/4; } else { errx(1, "%s: wrong checksum", bootnam); /* NOTREACHED */ } if (sum2 == sum16) { warnx("eek - both sums are the same"); } if (line) { dline = (char *)&(block[CMDLN_LOC/4]); /* XXX keep the default default line in sync with bbstart.s */ if (strcmp(dline, "netbsd -ASn2") != 0) { errx(1, "Old bootblock version? Can't change command line."); } (void)strncpy(dline, line, CMDLN_LEN-1); block[1] = 0; block[1] = 0xffffffff - chksum(block, sumlen); } rc = write(devfd, block, sizeof(block)); if (rc < sizeof(block)) { err(1, "Can't write bootblock"); /* NOTREACHED */ } exit(1); /* NOTREACHED */ }