int main(int argc, char *argv[]) { int c; int devfd; char *protostore; size_t protosize; while ((c = getopt(argc, argv, "vnh")) != -1) { switch (c) { case 'h': /* Don't strip a.out header */ hflag = 1; break; case 'n': /* Do not actually write the bootblock to disk */ nowrite = 1; break; case 'v': /* Chat */ verbose = 1; break; default: usage(); } } if (argc - optind < 3) { usage(); } boot = argv[optind]; proto = argv[optind + 1]; dev = argv[optind + 2]; if (verbose) { printf("boot: %s\n", boot); printf("proto: %s\n", proto); printf("device: %s\n", dev); } /* Load proto blocks into core */ if ((protostore = loadprotoblocks(proto, &protosize)) == NULL) exit(1); /* XXX - Paranoia: Make sure size is aligned! */ if (protosize & (DEV_BSIZE - 1)) err(1, "proto bootblock bad size=%d", protosize); /* Open and check raw disk device */ if ((devfd = open(dev, O_RDONLY, 0)) < 0) err(1, "open: %s", dev); /* Extract and load block numbers */ if (loadblocknums(boot, devfd) != 0) exit(1); (void)close(devfd); if (nowrite) return 0; /* Write patched proto bootblocks into the superblock */ if (protosize > SBLOCKSIZE - DEV_BSIZE) errx(1, "proto bootblocks too big"); /* The primary bootblock needs to be written to the raw partition */ dev[strlen(dev) - 1] = 'a' + RAW_PART; if ((devfd = open(dev, O_RDWR, 0)) < 0) err(1, "open: %s", dev); if (lseek(devfd, DEV_BSIZE, SEEK_SET) != DEV_BSIZE) err(1, "lseek bootstrap"); /* Sync filesystems (to clean in-memory superblock?) */ sync(); if (write(devfd, protostore, protosize) != protosize) err(1, "write bootstrap"); (void)close(devfd); return 0; }
int main(int argc, char *argv[]) { int c, devfd; char *protostore; long protosize; struct stat disksb, bootsb; struct disklabel dl; daddr64_t partoffset; #define BBPAD 0x1e0 struct bb { char bb_pad[BBPAD]; /* disklabel lives in here, actually */ long bb_secsize; /* size of secondary boot block */ long bb_secstart; /* start of secondary boot block */ long bb_flags; /* unknown; always zero */ long bb_cksum; /* checksum of the boot block, as longs. */ } bb; long *lp, *ep; while ((c = getopt(argc, argv, "vns:e:")) != -1) { switch (c) { case 'n': /* Do not actually write the bootblock to disk */ nowrite = 1; break; case 'v': /* Chat */ verbose = 1; break; case 's': isofsblk = atoi(optarg); break; case 'e': isofseblk = atoi(optarg); break; default: usage(); } } if (argc - optind < 3) usage(); boot = argv[optind]; proto = argv[optind + 1]; dev = argv[optind + 2]; if (verbose) { (void)printf("boot: %s\n", boot); (void)printf("proto: %s\n", proto); (void)printf("device: %s\n", dev); } /* Load proto blocks into core */ if ((protostore = loadprotoblocks(proto, &protosize)) == NULL) exit(1); /* Open and check raw disk device */ if ((devfd = opendev(dev, O_RDONLY, OPENDEV_PART, &dev)) < 0) err(1, "open: %s", dev); if (fstat(devfd, &disksb) == -1) err(1, "fstat: %s", dev); if (!S_ISCHR(disksb.st_mode)) errx(1, "%s must be a character device node", dev); if ((minor(disksb.st_rdev) % getmaxpartitions()) != getrawpartition()) errx(1, "%s must be the raw partition", dev); /* Extract and load block numbers */ if (stat(boot, &bootsb) == -1) err(1, "stat: %s", boot); if (!S_ISREG(bootsb.st_mode)) errx(1, "%s must be a regular file", boot); if ((minor(disksb.st_rdev) / getmaxpartitions()) != (minor(bootsb.st_dev) / getmaxpartitions())) errx(1, "%s must be somewhere on %s", boot, dev); /* * Find the offset of the secondary boot block's partition * into the disk. If disklabels not supported, assume zero. */ if (ioctl(devfd, DIOCGDINFO, &dl) != -1) { partoffset = DL_GETPOFFSET(&dl.d_partitions[minor(bootsb.st_dev) % getmaxpartitions()]); } else { if (errno != ENOTTY) err(1, "read disklabel: %s", dev); warnx("couldn't read label from %s, using part offset of 0", dev); partoffset = 0; } if (verbose) (void)printf("%s partition offset = 0x%lx\n", boot, partoffset); /* Sync filesystems (make sure boot's block numbers are stable) */ sync(); sleep(2); sync(); sleep(2); if (loadblocknums(boot, devfd, partoffset) != 0) exit(1); (void)close(devfd); if (nowrite) return 0; #if 0 /* Write patched proto bootblocks into the superblock */ if (protosize > SBSIZE - DEV_BSIZE) errx(1, "proto bootblocks too big"); #endif if ((devfd = opendev(dev, O_RDWR, OPENDEV_PART, &dev)) < 0) err(1, "open: %s", dev); if (lseek(devfd, DEV_BSIZE, SEEK_SET) != DEV_BSIZE) err(1, "lseek bootstrap"); if (write(devfd, protostore, protosize) != protosize) err(1, "write bootstrap"); if (lseek(devfd, 0, SEEK_SET) != 0) err(1, "lseek label"); if (read(devfd, &bb, sizeof (bb)) != sizeof (bb)) err(1, "read label"); bb.bb_secsize = 15; bb.bb_secstart = 1; bb.bb_flags = 0; bb.bb_cksum = 0; for (lp = (long *)&bb, ep = &bb.bb_cksum; lp < ep; lp++) bb.bb_cksum += *lp; if (lseek(devfd, 0, SEEK_SET) != 0) err(1, "lseek label 2"); if (write(devfd, &bb, sizeof bb) != sizeof bb) err(1, "write label "); (void)close(devfd); return 0; }