10b654f60SRobert Nordier /* 20b654f60SRobert Nordier * Copyright (c) 1999 Robert Nordier 30b654f60SRobert Nordier * All rights reserved. 40b654f60SRobert Nordier * 50b654f60SRobert Nordier * Redistribution and use in source and binary forms, with or without 60b654f60SRobert Nordier * modification, are permitted provided that the following conditions 70b654f60SRobert Nordier * are met: 80b654f60SRobert Nordier * 1. Redistributions of source code must retain the above copyright 90b654f60SRobert Nordier * notice, this list of conditions and the following disclaimer. 100b654f60SRobert Nordier * 2. Redistributions in binary form must reproduce the above copyright 110b654f60SRobert Nordier * notice, this list of conditions and the following disclaimer in the 120b654f60SRobert Nordier * documentation and/or other materials provided with the distribution. 130b654f60SRobert Nordier * 140b654f60SRobert Nordier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 150b654f60SRobert Nordier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160b654f60SRobert Nordier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 170b654f60SRobert Nordier * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 180b654f60SRobert Nordier * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 190b654f60SRobert Nordier * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 200b654f60SRobert Nordier * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 210b654f60SRobert Nordier * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 220b654f60SRobert Nordier * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 230b654f60SRobert Nordier * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 240b654f60SRobert Nordier * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 250b654f60SRobert Nordier */ 260b654f60SRobert Nordier 270b654f60SRobert Nordier #ifndef lint 280b654f60SRobert Nordier static const char rcsid[] = 29ee6fb785SRobert Nordier "$Id: boot0cfg.c,v 1.2 1999/02/22 09:36:54 rnordier Exp $"; 300b654f60SRobert Nordier #endif /* not lint */ 310b654f60SRobert Nordier 320b654f60SRobert Nordier #include <sys/param.h> 330b654f60SRobert Nordier #include <sys/disklabel.h> 340b654f60SRobert Nordier #include <sys/stat.h> 350b654f60SRobert Nordier 360b654f60SRobert Nordier #include <err.h> 370b654f60SRobert Nordier #include <errno.h> 380b654f60SRobert Nordier #include <fcntl.h> 390b654f60SRobert Nordier #include <paths.h> 400b654f60SRobert Nordier #include <stdio.h> 410b654f60SRobert Nordier #include <stdlib.h> 420b654f60SRobert Nordier #include <string.h> 430b654f60SRobert Nordier #include <unistd.h> 440b654f60SRobert Nordier 450b654f60SRobert Nordier #define MBRSIZE 512 /* master boot record size */ 460b654f60SRobert Nordier 47ee6fb785SRobert Nordier #define OFF_DRIVE 0x1ba /* offset: setdrv drive */ 480b654f60SRobert Nordier #define OFF_FLAGS 0x1bb /* offset: option flags */ 490b654f60SRobert Nordier #define OFF_TICKS 0x1bc /* offset: clock ticks */ 500b654f60SRobert Nordier #define OFF_PTBL 0x1be /* offset: partition table */ 510b654f60SRobert Nordier #define OFF_MAGIC 0x1fe /* offset: magic number */ 520b654f60SRobert Nordier 530b654f60SRobert Nordier #define cv2(p) ((p)[0] | (p)[1] << 010) 540b654f60SRobert Nordier 550b654f60SRobert Nordier #define mk2(p, x) \ 560b654f60SRobert Nordier (p)[0] = (u_int8_t)(x), \ 570b654f60SRobert Nordier (p)[1] = (u_int8_t)((x) >> 010) 580b654f60SRobert Nordier 590b654f60SRobert Nordier static const struct { 600b654f60SRobert Nordier const char *tok; 610b654f60SRobert Nordier int def; 620b654f60SRobert Nordier } opttbl[] = { 630b654f60SRobert Nordier {"packet", 0}, 640b654f60SRobert Nordier {"update", 1}, 650b654f60SRobert Nordier {"setdrv", 0} 660b654f60SRobert Nordier }; 670b654f60SRobert Nordier static const int nopt = sizeof(opttbl) / sizeof(opttbl[0]); 680b654f60SRobert Nordier 690b654f60SRobert Nordier static const char fmt0[] = "# flag start chs type" 700b654f60SRobert Nordier " end chs offset size\n"; 710b654f60SRobert Nordier 720b654f60SRobert Nordier static const char fmt1[] = "%d 0x%02x %4u:%3u:%2u 0x%02x" 730b654f60SRobert Nordier " %4u:%3u:%2u %10u %10u\n"; 740b654f60SRobert Nordier 750b654f60SRobert Nordier static void stropt(const char *, int *, int *); 760b654f60SRobert Nordier static char *mkrdev(const char *); 770b654f60SRobert Nordier static int argtoi(const char *, int, int, int); 780b654f60SRobert Nordier static void usage(void); 790b654f60SRobert Nordier 800b654f60SRobert Nordier int 810b654f60SRobert Nordier main(int argc, char *argv[]) 820b654f60SRobert Nordier { 830b654f60SRobert Nordier u_int8_t buf[MBRSIZE]; 840b654f60SRobert Nordier struct dos_partition part[4]; 850b654f60SRobert Nordier const char *bpath, *fpath, *disk; 860b654f60SRobert Nordier ssize_t n; 870b654f60SRobert Nordier int B_flag, v_flag, o_flag; 880b654f60SRobert Nordier int d_arg, t_arg; 890b654f60SRobert Nordier int o_and, o_or; 900b654f60SRobert Nordier int fd, fd1, up, c, i; 910b654f60SRobert Nordier 920b654f60SRobert Nordier bpath = "/boot/boot0"; 930b654f60SRobert Nordier fpath = NULL; 940b654f60SRobert Nordier B_flag = v_flag = o_flag = 0; 950b654f60SRobert Nordier d_arg = t_arg = -1; 960b654f60SRobert Nordier o_and = 0xff; 970b654f60SRobert Nordier o_or = 0; 980b654f60SRobert Nordier while ((c = getopt(argc, argv, "Bvb:d:f:o:t:")) != -1) 990b654f60SRobert Nordier switch (c) { 1000b654f60SRobert Nordier case 'B': 1010b654f60SRobert Nordier B_flag = 1; 1020b654f60SRobert Nordier break; 1030b654f60SRobert Nordier case 'v': 1040b654f60SRobert Nordier v_flag = 1; 1050b654f60SRobert Nordier break; 1060b654f60SRobert Nordier case 'b': 1070b654f60SRobert Nordier bpath = optarg; 1080b654f60SRobert Nordier break; 1090b654f60SRobert Nordier case 'd': 1100b654f60SRobert Nordier d_arg = argtoi(optarg, 0, 0xff, 'd'); 1110b654f60SRobert Nordier break; 1120b654f60SRobert Nordier case 'f': 1130b654f60SRobert Nordier fpath = optarg; 1140b654f60SRobert Nordier break; 1150b654f60SRobert Nordier case 'o': 1160b654f60SRobert Nordier stropt(optarg, &o_and, &o_or); 1170b654f60SRobert Nordier o_flag = 1; 1180b654f60SRobert Nordier break; 1190b654f60SRobert Nordier case 't': 1200b654f60SRobert Nordier t_arg = argtoi(optarg, 1, 0xffff, 't'); 1210b654f60SRobert Nordier break; 1220b654f60SRobert Nordier default: 1230b654f60SRobert Nordier usage(); 1240b654f60SRobert Nordier } 1250b654f60SRobert Nordier argc -= optind; 1260b654f60SRobert Nordier argv += optind; 1270b654f60SRobert Nordier if (argc != 1) 1280b654f60SRobert Nordier usage(); 1290b654f60SRobert Nordier disk = mkrdev(*argv); 130ed720ec3SRobert Nordier up = B_flag || d_arg != -1 || o_flag || t_arg != -1; 1310b654f60SRobert Nordier if ((fd = open(disk, up ? O_RDWR : O_RDONLY)) == -1) 1320b654f60SRobert Nordier err(1, "%s", disk); 1330b654f60SRobert Nordier if ((n = read(fd, buf, MBRSIZE)) == -1) 1340b654f60SRobert Nordier err(1, "%s", disk); 1350b654f60SRobert Nordier if (n != MBRSIZE) 1360b654f60SRobert Nordier errx(1, "%s: short read", disk); 1370b654f60SRobert Nordier if (cv2(buf + OFF_MAGIC) != 0xaa55) 1380b654f60SRobert Nordier errx(1, "%s: bad magic", disk); 1390b654f60SRobert Nordier if (fpath) { 1400b654f60SRobert Nordier if ((fd1 = open(fpath, O_WRONLY | O_CREAT | O_TRUNC, 1410b654f60SRobert Nordier 0666)) == -1 || 1420b654f60SRobert Nordier (n = write(fd1, buf, MBRSIZE)) == -1 || close(fd1)) 1430b654f60SRobert Nordier err(1, "%s", fpath); 1440b654f60SRobert Nordier if (n != MBRSIZE) 1450b654f60SRobert Nordier errx(1, "%s: short write", fpath); 1460b654f60SRobert Nordier } 1470b654f60SRobert Nordier memcpy(part, buf + OFF_PTBL, sizeof(part)); 1480b654f60SRobert Nordier if (B_flag) { 1490b654f60SRobert Nordier if ((fd1 = open(bpath, O_RDONLY)) == -1 || 1500b654f60SRobert Nordier (n = read(fd1, buf, MBRSIZE)) == -1 || close(fd1)) 1510b654f60SRobert Nordier err(1, "%s", bpath); 1520b654f60SRobert Nordier if (n != MBRSIZE) 1530b654f60SRobert Nordier errx(1, "%s: short read", bpath); 1540b654f60SRobert Nordier if (cv2(buf + OFF_MAGIC) != 0xaa55) 1550b654f60SRobert Nordier errx(1, "%s: bad magic", bpath); 1560b654f60SRobert Nordier memcpy(buf + OFF_PTBL, part, sizeof(part)); 1570b654f60SRobert Nordier } 158ee6fb785SRobert Nordier if (d_arg != -1) 159ee6fb785SRobert Nordier buf[OFF_DRIVE] = d_arg; 1600b654f60SRobert Nordier if (o_flag) { 1610b654f60SRobert Nordier buf[OFF_FLAGS] &= o_and; 1620b654f60SRobert Nordier buf[OFF_FLAGS] |= o_or; 1630b654f60SRobert Nordier } 1640b654f60SRobert Nordier if (t_arg != -1) 1650b654f60SRobert Nordier mk2(buf + OFF_TICKS, t_arg); 1660b654f60SRobert Nordier if (up) { 1670b654f60SRobert Nordier if (lseek(fd, 0, SEEK_SET) == -1 || 1680b654f60SRobert Nordier (n = write(fd, buf, MBRSIZE)) == -1 || close(fd)) 1690b654f60SRobert Nordier err(1, "%s", disk); 1700b654f60SRobert Nordier if (n != MBRSIZE) 1710b654f60SRobert Nordier errx(1, "%s: short write", disk); 1720b654f60SRobert Nordier } 1730b654f60SRobert Nordier if (v_flag) { 1740b654f60SRobert Nordier printf(fmt0); 1750b654f60SRobert Nordier for (i = 0; i < 4; i++) 1760b654f60SRobert Nordier if (part[i].dp_typ) { 1770b654f60SRobert Nordier printf(fmt1, 1780b654f60SRobert Nordier 1 + i, 1790b654f60SRobert Nordier part[i].dp_flag, 1800b654f60SRobert Nordier part[i].dp_scyl + ((part[i].dp_ssect & 0xc0) << 2), 1810b654f60SRobert Nordier part[i].dp_shd, 1820b654f60SRobert Nordier part[i].dp_ssect & 0x3f, 1830b654f60SRobert Nordier part[i].dp_typ, 1840b654f60SRobert Nordier part[i].dp_ecyl + ((part[i].dp_esect & 0xc0) << 2), 1850b654f60SRobert Nordier part[i].dp_ehd, 1860b654f60SRobert Nordier part[i].dp_esect & 0x3f, 1870b654f60SRobert Nordier part[i].dp_start, 1880b654f60SRobert Nordier part[i].dp_size); 1890b654f60SRobert Nordier } 1900b654f60SRobert Nordier printf("\n"); 191ee6fb785SRobert Nordier printf("drive=0x%x options=", buf[OFF_DRIVE]); 1920b654f60SRobert Nordier for (i = 0; i < nopt; i++) { 1930b654f60SRobert Nordier if (i) 1940b654f60SRobert Nordier printf(","); 1950b654f60SRobert Nordier if (!(buf[OFF_FLAGS] & 1 << (7 - i)) ^ opttbl[i].def) 1960b654f60SRobert Nordier printf("no"); 1970b654f60SRobert Nordier printf("%s", opttbl[i].tok); 1980b654f60SRobert Nordier } 1990b654f60SRobert Nordier printf(" ticks=%u\n", cv2(buf + OFF_TICKS)); 2000b654f60SRobert Nordier } 2010b654f60SRobert Nordier return 0; 2020b654f60SRobert Nordier } 2030b654f60SRobert Nordier 2040b654f60SRobert Nordier static void 2050b654f60SRobert Nordier stropt(const char *arg, int *xa, int *xo) 2060b654f60SRobert Nordier { 2070b654f60SRobert Nordier const char *q; 2080b654f60SRobert Nordier char *s, *s1; 2090b654f60SRobert Nordier int inv, i, x; 2100b654f60SRobert Nordier 2110b654f60SRobert Nordier if (!(s = strdup(arg))) 2120b654f60SRobert Nordier err(1, NULL); 2130b654f60SRobert Nordier for (s1 = s; (q = strtok(s1, ",")); s1 = NULL) { 2140b654f60SRobert Nordier if ((inv = !strncmp(q, "no", 2))) 2150b654f60SRobert Nordier q += 2; 2160b654f60SRobert Nordier for (i = 0; i < nopt; i++) 2170b654f60SRobert Nordier if (!strcmp(q, opttbl[i].tok)) 2180b654f60SRobert Nordier break; 2190b654f60SRobert Nordier if (i == nopt) 2200b654f60SRobert Nordier errx(1, "%s: Unknown -o option", q); 2210b654f60SRobert Nordier if (opttbl[i].def) 2220b654f60SRobert Nordier inv ^= 1; 2230b654f60SRobert Nordier x = 1 << (7 - i); 2240b654f60SRobert Nordier if (inv) 2250b654f60SRobert Nordier *xa &= ~x; 2260b654f60SRobert Nordier else 2270b654f60SRobert Nordier *xo |= x; 2280b654f60SRobert Nordier } 2290b654f60SRobert Nordier free(s); 2300b654f60SRobert Nordier } 2310b654f60SRobert Nordier 2320b654f60SRobert Nordier static char * 2330b654f60SRobert Nordier mkrdev(const char *fname) 2340b654f60SRobert Nordier { 2350b654f60SRobert Nordier char buf[MAXPATHLEN]; 2360b654f60SRobert Nordier struct stat sb; 2370b654f60SRobert Nordier char *s; 2380b654f60SRobert Nordier 2390b654f60SRobert Nordier s = (char *) fname; 2400b654f60SRobert Nordier if (!strchr(fname, '/')) { 2410b654f60SRobert Nordier snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname); 2420b654f60SRobert Nordier if (stat(buf, &sb)) 2430b654f60SRobert Nordier snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); 2440b654f60SRobert Nordier if (!(s = strdup(buf))) 2450b654f60SRobert Nordier err(1, NULL); 2460b654f60SRobert Nordier } 2470b654f60SRobert Nordier return s; 2480b654f60SRobert Nordier } 2490b654f60SRobert Nordier 2500b654f60SRobert Nordier static int 2510b654f60SRobert Nordier argtoi(const char *arg, int lo, int hi, int opt) 2520b654f60SRobert Nordier { 2530b654f60SRobert Nordier char *s; 2540b654f60SRobert Nordier long x; 2550b654f60SRobert Nordier 2560b654f60SRobert Nordier errno = 0; 2570b654f60SRobert Nordier x = strtol(arg, &s, 0); 2580b654f60SRobert Nordier if (errno || !*arg || *s || x < lo || x > hi) 2590b654f60SRobert Nordier errx(1, "%s: Bad argument to -%c option", arg, opt); 2600b654f60SRobert Nordier return x; 2610b654f60SRobert Nordier } 2620b654f60SRobert Nordier 2630b654f60SRobert Nordier static void 2640b654f60SRobert Nordier usage(void) 2650b654f60SRobert Nordier { 2660b654f60SRobert Nordier fprintf(stderr, "%s\n%s\n", 2670b654f60SRobert Nordier "usage: boot0cfg [-Bv] [-b boot0] [-d drive] [-f file] [-o options]", 2680b654f60SRobert Nordier " [-t ticks] disk"); 2690b654f60SRobert Nordier exit(1); 2700b654f60SRobert Nordier } 271