void write_bootblocks(int devfd, struct disklabel *dl) { struct stat sb; u_int8_t *secbuf; u_int start = 0; /* Write patched proto bootblock(s) into the superblock. */ if (fstat(devfd, &sb) < 0) err(1, "stat: %s", realdev); if (!S_ISCHR(sb.st_mode)) errx(1, "%s: not a character device", realdev); /* Patch the parameters into the proto bootstrap sector. */ pbr_set_symbols(proto, protostore, pbr_symbols); if (!nowrite) { /* Sync filesystems (to clean in-memory superblock?). */ sync(); sleep(1); } /* * Find OpenBSD partition. Floppies are special, getting an * everything-in-one biosboot starting at sector 0. */ if (dl->d_type != DTYPE_FLOPPY) { start = findopenbsd(devfd, dl); if (start == (u_int)-1) errx(1, "no Bitrig partition"); } if (verbose) fprintf(stderr, "%s will be written at sector %u\n", proto, start); if (start + (protosize / dl->d_secsize) > BOOTBIOS_MAXSEC) warnx("%s extends beyond sector %u. Bitrig might not boot.", proto, BOOTBIOS_MAXSEC); if (!nowrite) { if (lseek(devfd, (off_t)start * dl->d_secsize, SEEK_SET) < 0) err(1, "seek bootstrap"); secbuf = calloc(1, dl->d_secsize); bcopy(protostore, secbuf, protosize); if (write(devfd, secbuf, dl->d_secsize) != dl->d_secsize) err(1, "write bootstrap"); free(secbuf); } }
void write_bootblocks(int devfd, struct disklabel *dl) { struct stat sb; u_int start = 0; /* Write patched proto bootblock(s) into the superblock. */ if (fstat(devfd, &sb) < 0) err(1, "stat: %s", realdev); if (!S_ISCHR(sb.st_mode)) errx(1, "%s: not a character device", realdev); /* Patch the parameters into the proto bootstrap sector. */ pbr_set_symbols(proto, protostore, pbr_symbols); if (!nowrite) { /* Sync filesystems (to clean in-memory superblock?). */ sync(); sleep(1); } if (dl->d_type != 0 && dl->d_type != DTYPE_FLOPPY && dl->d_type != DTYPE_VND) { /* Find OpenBSD partition. */ start = findopenbsd(devfd, dl); if (start == (u_int)-1) errx(1, "no OpenBSD partition"); } if (start + (protosize / DEV_BSIZE) > BOOTBIOS_MAXSEC) errx(1, "invalid location: all of /boot must be < sector %u.", BOOTBIOS_MAXSEC); if (verbose) fprintf(stderr, "/boot will be written at sector %u\n", start); if (!nowrite) { if (lseek(devfd, (off_t)start * dl->d_secsize, SEEK_SET) < 0 || write(devfd, protostore, protosize) != protosize) err(1, "write bootstrap"); } }
/* * Read information about /boot's inode and filesystem parameters, then * put biosboot (partition boot record) on the target drive with these * parameters patched in. */ int main(int argc, char *argv[]) { int c; int devfd; char *protostore; long protosize; struct stat sb; struct disklabel dl; struct dos_mbr mbr; struct dos_partition *dp; off_t startoff = 0; while ((c = getopt(argc, argv, "vn")) != -1) { switch (c) { case 'n': /* Do not actually write the bootblock to disk. */ nowrite = 1; break; case 'v': /* Give more information. */ verbose = 1; break; default: usage(); } } if (argc - optind < 3) usage(); boot = argv[optind]; proto = argv[optind + 1]; realdev = dev = argv[optind + 2]; /* Open and check raw disk device. */ if ((devfd = opendev(dev, (nowrite? O_RDONLY:O_RDWR), OPENDEV_PART, &realdev)) < 0) err(1, "open: %s", realdev); if (verbose) { fprintf(stderr, "boot: %s\n", boot); fprintf(stderr, "proto: %s\n", proto); fprintf(stderr, "device: %s\n", realdev); } if (ioctl(devfd, DIOCGDINFO, &dl) != 0) err(1, "disklabel: %s", realdev); /* Check disklabel. */ if (dl.d_magic != DISKMAGIC) err(1, "bad disklabel magic=0x%08x", dl.d_magic); /* Warn on unknown disklabel types. */ if (dl.d_type == 0) warnx("disklabel type unknown"); /* Load proto blocks into core. */ if ((protostore = loadproto(proto, &protosize)) == NULL) exit(1); /* XXX - Paranoia: Make sure size is aligned! */ if (protosize & (DEV_BSIZE - 1)) errx(1, "proto %s bad size=%ld", proto, protosize); /* Write patched proto bootblock(s) into the superblock. */ if (protosize > SBSIZE - DEV_BSIZE) errx(1, "proto bootblocks too big"); if (fstat(devfd, &sb) < 0) err(1, "stat: %s", realdev); if (!S_ISCHR(sb.st_mode)) errx(1, "%s: not a character device", realdev); /* Get bootstrap parameters that are to be patched into proto. */ if (getbootparams(boot, devfd, &dl) != 0) exit(1); /* Patch the parameters into the proto bootstrap sector. */ pbr_set_symbols(proto, protostore, pbr_symbols); if (!nowrite) { /* Sync filesystems (to clean in-memory superblock?). */ sync(); sleep(1); } if (dl.d_type != 0 && dl.d_type != DTYPE_FLOPPY && dl.d_type != DTYPE_VND) { if (lseek(devfd, (off_t)DOSBBSECTOR, SEEK_SET) < 0 || read(devfd, &mbr, sizeof(mbr)) < sizeof(mbr)) err(4, "can't read master boot record"); if (mbr.dmbr_sign != DOSMBR_SIGNATURE) errx(1, "broken MBR"); /* Find OpenBSD partition. */ for (dp = mbr.dmbr_parts; dp < &mbr.dmbr_parts[NDOSPART]; dp++) { if (dp->dp_size && dp->dp_typ == DOSPTYP_OPENBSD) { startoff = (off_t)dp->dp_start * dl.d_secsize; fprintf(stderr, "using MBR partition %ld: " "type %d (0x%02x) offset %d (0x%x)\n", (long)(dp - mbr.dmbr_parts), dp->dp_typ, dp->dp_typ, dp->dp_start, dp->dp_start); break; } } /* Don't check for old part number, that is ;-p */ if (dp >= &mbr.dmbr_parts[NDOSPART]) errx(1, "no OpenBSD partition"); } if (!nowrite) { if (lseek(devfd, startoff, SEEK_SET) < 0 || write(devfd, protostore, protosize) != protosize) err(1, "write bootstrap"); } (void)close(devfd); return 0; }