Home | History | Annotate | Line # | Download | only in installboot
installboot.c revision 1.17.2.1
      1 /*	$NetBSD: installboot.c,v 1.17.2.1 2004/08/03 10:33:26 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Waldi Ravens
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *        This product includes software developed by Waldi Ravens.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/types.h>
     34 #include <sys/param.h>
     35 #include <sys/sysctl.h>
     36 #include <sys/ioctl.h>
     37 #include <unistd.h>
     38 #include <string.h>
     39 #include <stdlib.h>
     40 #include <stdio.h>
     41 #include <paths.h>
     42 #include <fcntl.h>
     43 #include <errno.h>
     44 #include <err.h>
     45 #include <limits.h>
     46 #include <nlist.h>
     47 #include <kvm.h>
     48 
     49 #define	DKTYPENAMES
     50 #define	FSTYPENAMES
     51 #include <sys/disklabel.h>
     52 #include <machine/ahdilabel.h>
     53 
     54 #include "installboot.h"
     55 
     56 static void	usage __P((void));
     57 static void	oscheck __P((void));
     58 static u_int	abcksum __P((void *));
     59 static void	setNVpref __P((void));
     60 static void	setIDEpar __P((u_int8_t *, size_t));
     61 static void	mkahdiboot __P((struct ahdi_root *, char *,
     62 						char *, daddr_t));
     63 static void	mkbootblock __P((struct bootblock *, char *,
     64 				char *, struct disklabel *, u_int));
     65 static void	install_fd __P((char *, struct disklabel *));
     66 static void	install_sd __P((char *, struct disklabel *));
     67 static void	install_wd __P((char *, struct disklabel *));
     68 
     69 static struct bootblock	bootarea;
     70 static struct ahdi_root ahdiboot;
     71 static const char	mdecpath[] = PATH_MDEC;
     72 static const char	stdpath[] = PATH_STD;
     73 static const char	milanpath[] = PATH_MILAN;
     74 static int		nowrite = 0;
     75 static int		verbose = 0;
     76 static int		trackpercyl = 0;
     77 static int		secpertrack = 0;
     78 static int		milan = 0;
     79 
     80 static void
     81 usage ()
     82 {
     83 	fprintf(stderr,
     84 		"usage: installboot [options] device\n"
     85 		"where options are:\n"
     86 		"\t-N  do not actually write anything on the disk\n"
     87 		"\t-m  use Milan boot blocks\n"
     88 		"\t-t  number of tracks per cylinder (IDE disk)\n"
     89 		"\t-u  number of sectors per track (IDE disk)\n"
     90 		"\t-v  verbose mode\n");
     91 	exit(EXIT_FAILURE);
     92 }
     93 
     94 int
     95 main (argc, argv)
     96 	int	argc;
     97 	char	*argv[];
     98 {
     99 	struct disklabel dl;
    100 	char		 *dn;
    101 	int		 fd, c;
    102 
    103 	/* check OS bootversion */
    104 	oscheck();
    105 
    106 	/* parse options */
    107 	while ((c = getopt(argc, argv, "Nmt:u:v")) != -1) {
    108 		switch (c) {
    109 		  case 'N':
    110 			nowrite = 1;
    111 			break;
    112 		  case 'm':
    113 			milan = 1;
    114 			break;
    115 		  case 't':
    116 			trackpercyl = atoi(optarg);
    117 			break;
    118 		  case 'u':
    119 			secpertrack = atoi(optarg);
    120 			break;
    121 		  case 'v':
    122 			verbose = 1;
    123 			break;
    124 		  default:
    125 			usage();
    126 		}
    127 	}
    128 	argv += optind;
    129 	argc -= optind;
    130 	if (argc != 1)
    131 		usage();
    132 
    133 	/* get disk label */
    134 	dn = alloca(sizeof(_PATH_DEV) + strlen(argv[0]) + 8);
    135 	if (!strchr(argv[0], '/')) {
    136 		sprintf(dn, "%sr%s%c", _PATH_DEV, argv[0], RAW_PART + 'a');
    137 		fd = open(dn, O_RDONLY);
    138 		if (fd < 0 && errno == ENOENT) {
    139 			sprintf(dn, "%sr%s", _PATH_DEV, argv[0]);
    140 			fd = open(dn, O_RDONLY);
    141 		}
    142 	} else {
    143 		sprintf(dn, "%s", argv[0]);
    144 		fd = open(dn, O_RDONLY);
    145 	}
    146 	if (fd < 0)
    147 		err(EXIT_FAILURE, "%s", dn);
    148 	if (ioctl(fd, DIOCGDINFO, &dl))
    149 		err(EXIT_FAILURE, "%s: DIOCGDINFO", dn);
    150 	if (close(fd))
    151 		err(EXIT_FAILURE, "%s", dn);
    152 
    153 	switch (dl.d_type) {
    154 		case DTYPE_FLOPPY:
    155 			install_fd(dn, &dl);
    156 			break;
    157 		case DTYPE_ST506:
    158 		case DTYPE_ESDI:
    159 			install_wd(dn, &dl);
    160 			setNVpref();
    161 			break;
    162 		case DTYPE_SCSI:
    163 			install_sd(dn, &dl);
    164 			setNVpref();
    165 			break;
    166 		default:
    167 			errx(EXIT_FAILURE,
    168 			     "%s: %s: Device type not supported.",
    169 			     dn, dktypenames[dl.d_type]);
    170 	}
    171 
    172 	return(EXIT_SUCCESS);
    173 }
    174 
    175 static void
    176 oscheck ()
    177 {
    178 	struct nlist	kbv[] = { { "_bootversion" },
    179 				  { NULL } };
    180 	kvm_t		*kd_kern;
    181 	char		errbuf[_POSIX2_LINE_MAX];
    182 	u_short		kvers;
    183 	struct stat	sb;
    184 
    185 	if (stat(_PATH_UNIX, &sb) < 0) {
    186 		warnx("Cannot stat %s, no bootversion check done", _PATH_UNIX);
    187 		return;
    188 	}
    189 
    190 	kd_kern = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
    191 	if (kd_kern == NULL)
    192 		errx(EXIT_FAILURE, "kvm_openfiles: %s", errbuf);
    193 	if (kvm_nlist(kd_kern, kbv) == -1)
    194 		errx(EXIT_FAILURE, "kvm_nlist: %s", kvm_geterr(kd_kern));
    195 	if (kbv[0].n_value == 0)
    196 		errx(EXIT_FAILURE, "%s not in namelist", kbv[0].n_name);
    197 	if (kvm_read(kd_kern, kbv[0].n_value, (char *)&kvers,
    198 						sizeof(kvers)) == -1)
    199 		errx(EXIT_FAILURE, "kvm_read: %s", kvm_geterr(kd_kern));
    200 	kvm_close(kd_kern);
    201 	if (kvers != BOOTVERSION)
    202 		errx(EXIT_FAILURE, "Kern bootversion: %d, expected: %d",
    203 					kvers, BOOTVERSION);
    204 }
    205 
    206 static void
    207 install_fd (devnm, label)
    208 	char		 *devnm;
    209 	struct disklabel *label;
    210 {
    211 	const char	 *machpath;
    212 	char		 *xxboot, *bootxx;
    213 	struct partition *rootpart;
    214 
    215 	if (label->d_secsize != 512)
    216 		errx(EXIT_FAILURE,
    217 		     "%s: %u: Block size not supported.", devnm,
    218 							  label->d_secsize);
    219 	if (label->d_ntracks != 2)
    220 		errx(EXIT_FAILURE,
    221 		     "%s: Single sided floppy not supported.", devnm);
    222 
    223 	if (milan)
    224 		machpath = milanpath;
    225 	else
    226 		machpath = stdpath;
    227 	xxboot = alloca(strlen(mdecpath) + strlen(machpath) + 8);
    228 	sprintf(xxboot, "%s%sfdboot", mdecpath, machpath);
    229 	bootxx = alloca(strlen(mdecpath) + strlen(machpath) + 8);
    230 	sprintf(bootxx, "%s%sbootxx", mdecpath, machpath);
    231 
    232 	/* first used partition (a, b or c) */		/* XXX */
    233 	for (rootpart = label->d_partitions; ; ++rootpart) {
    234 		if (rootpart->p_size)
    235 			break;
    236 	}
    237 	if (rootpart != label->d_partitions) {		/* XXX */
    238 		*(label->d_partitions) = *rootpart;
    239 		memset(rootpart, 0, sizeof(*rootpart));
    240 	}
    241 	label->d_partitions->p_fstype = FS_BSDFFS;	/* XXX */
    242 	label->d_npartitions = 1;
    243 	label->d_checksum = 0;
    244 	label->d_checksum = dkcksum(label);
    245 
    246 	trackpercyl = secpertrack = 0;
    247 	mkbootblock(&bootarea, xxboot, bootxx, label, 0);
    248 
    249 	if (!nowrite) {
    250 		int	fd;
    251 		if ((fd = open(devnm, O_WRONLY)) < 0)
    252 			err(EXIT_FAILURE, "%s", devnm);
    253 		if (write(fd, &bootarea, sizeof(bootarea)) != sizeof(bootarea))
    254 			err(EXIT_FAILURE, "%s", devnm);
    255 		if (close(fd))
    256 			err(EXIT_FAILURE, "%s", devnm);
    257 		if (verbose)
    258 			printf("Boot block installed on %s\n", devnm);
    259 	}
    260 }
    261 
    262 static void
    263 install_sd (devnm, label)
    264 	char		 *devnm;
    265 	struct disklabel *label;
    266 {
    267 	const char	 *machpath;
    268 	char		 *xxb00t, *xxboot, *bootxx;
    269 	struct disklabel rawlabel;
    270 	daddr_t		 bbsec;
    271 	u_int		 magic;
    272 
    273 	if (label->d_partitions[0].p_size == 0)
    274 		errx(EXIT_FAILURE, "%s: No root-filesystem.", devnm);
    275 	if (label->d_partitions[0].p_fstype != FS_BSDFFS)
    276 		errx(EXIT_FAILURE, "%s: %s: Illegal root-filesystem type.",
    277 		     devnm, fstypenames[label->d_partitions[0].p_fstype]);
    278 
    279 	bbsec = readdisklabel(devnm, &rawlabel);
    280 	if (bbsec == NO_BOOT_BLOCK)
    281 		errx(EXIT_FAILURE, "%s: No NetBSD boot block.", devnm);
    282 	if (memcmp(label, &rawlabel, sizeof(*label)))
    283 		errx(EXIT_FAILURE, "%s: Invalid NetBSD boot block.", devnm);
    284 
    285 	if (milan)
    286 		machpath = milanpath;
    287 	else
    288 		machpath = stdpath;
    289 	if (bbsec) {
    290 		xxb00t = alloca(strlen(mdecpath) + strlen(machpath) + 14);
    291 		sprintf(xxb00t, "%s%ssdb00t.ahdi", mdecpath, machpath);
    292 		xxboot = alloca(strlen(mdecpath) + strlen(machpath) + 14);
    293 		sprintf(xxboot, "%s%sxxboot.ahdi", mdecpath, machpath);
    294 		magic = AHDIMAGIC;
    295 	} else {
    296 		xxb00t = NULL;
    297 		xxboot = alloca(strlen(mdecpath) + strlen(machpath) + 8);
    298 		sprintf(xxboot, "%s%ssdboot", mdecpath, machpath);
    299 		magic = NBDAMAGIC;
    300 	}
    301 	bootxx = alloca(strlen(mdecpath) + strlen(machpath) + 8);
    302 	sprintf(bootxx, "%s%sbootxx", mdecpath, machpath);
    303 
    304 	trackpercyl = secpertrack = 0;
    305 	if (xxb00t)
    306 		mkahdiboot(&ahdiboot, xxb00t, devnm, bbsec);
    307 	mkbootblock(&bootarea, xxboot, bootxx, label, magic);
    308 
    309 	if (!nowrite) {
    310 		off_t	bbo = bbsec * AHDI_BSIZE;
    311 		int	fd;
    312 
    313 		if ((fd = open(devnm, O_WRONLY)) < 0)
    314 			err(EXIT_FAILURE, "%s", devnm);
    315 		if (lseek(fd, bbo, SEEK_SET) != bbo)
    316 			err(EXIT_FAILURE, "%s", devnm);
    317 		if (write(fd, &bootarea, sizeof(bootarea)) != sizeof(bootarea))
    318 			err(EXIT_FAILURE, "%s", devnm);
    319 		if (verbose)
    320 			printf("Boot block installed on %s (sector %d)\n", devnm,
    321 								    bbsec);
    322 		if (xxb00t) {
    323 			if (lseek(fd, (off_t)0, SEEK_SET) != 0)
    324 				err(EXIT_FAILURE, "%s", devnm);
    325 			if (write(fd, &ahdiboot, sizeof(ahdiboot)) != sizeof(ahdiboot))
    326 				err(EXIT_FAILURE, "%s", devnm);
    327 			if (verbose)
    328 				printf("AHDI root  installed on %s (0)\n",
    329 								devnm);
    330 		}
    331 		if (close(fd))
    332 			err(EXIT_FAILURE, "%s", devnm);
    333 	}
    334 }
    335 
    336 static void
    337 install_wd (devnm, label)
    338 	char		 *devnm;
    339 	struct disklabel *label;
    340 {
    341 	const char	 *machpath;
    342 	char		 *xxb00t, *xxboot, *bootxx;
    343 	struct disklabel rawlabel;
    344 	daddr_t		 bbsec;
    345 	u_int		 magic;
    346 
    347 	if (label->d_partitions[0].p_size == 0)
    348 		errx(EXIT_FAILURE, "%s: No root-filesystem.", devnm);
    349 	if (label->d_partitions[0].p_fstype != FS_BSDFFS)
    350 		errx(EXIT_FAILURE, "%s: %s: Illegal root-filesystem type.",
    351 		     devnm, fstypenames[label->d_partitions[0].p_fstype]);
    352 
    353 	bbsec = readdisklabel(devnm, &rawlabel);
    354 	if (bbsec == NO_BOOT_BLOCK)
    355 		errx(EXIT_FAILURE, "%s: No NetBSD boot block.", devnm);
    356 	if (memcmp(label, &rawlabel, sizeof(*label)))
    357 		errx(EXIT_FAILURE, "%s: Invalid NetBSD boot block.", devnm);
    358 
    359 	if (milan)
    360 		machpath = milanpath;
    361 	else
    362 		machpath = stdpath;
    363 	if (bbsec) {
    364 		xxb00t = alloca(strlen(mdecpath) + strlen(machpath) + 14);
    365 		sprintf(xxb00t, "%s%swdb00t.ahdi", mdecpath, machpath);
    366 		xxboot = alloca(strlen(mdecpath) + strlen(machpath) + 14);
    367 		sprintf(xxboot, "%s%sxxboot.ahdi", mdecpath, machpath);
    368 		magic = AHDIMAGIC;
    369 	} else {
    370 		xxb00t = NULL;
    371 		xxboot = alloca(strlen(mdecpath) + strlen(machpath) + 8);
    372 		sprintf(xxboot, "%s%swdboot", mdecpath, machpath);
    373 		magic = NBDAMAGIC;
    374 	}
    375 	bootxx = alloca(strlen(mdecpath) + strlen(machpath) + 8);
    376 	sprintf(bootxx, "%s%sbootxx", mdecpath, machpath);
    377 
    378 	if (xxb00t)
    379 		mkahdiboot(&ahdiboot, xxb00t, devnm, bbsec);
    380 	mkbootblock(&bootarea, xxboot, bootxx, label, magic);
    381 
    382 	if (!nowrite) {
    383 		int	fd;
    384 		off_t	bbo;
    385 
    386 		bbo = bbsec * AHDI_BSIZE;
    387 		if ((fd = open(devnm, O_WRONLY)) < 0)
    388 			err(EXIT_FAILURE, "%s", devnm);
    389 		if (lseek(fd, bbo, SEEK_SET) != bbo)
    390 			err(EXIT_FAILURE, "%s", devnm);
    391 		if (write(fd, &bootarea, sizeof(bootarea)) != sizeof(bootarea))
    392 			err(EXIT_FAILURE, "%s", devnm);
    393 		if (verbose)
    394 			printf("Boot block installed on %s (sector %d)\n", devnm,
    395 								    bbsec);
    396 		if (xxb00t) {
    397 			if (lseek(fd, (off_t)0, SEEK_SET) != 0)
    398 				err(EXIT_FAILURE, "%s", devnm);
    399 			if (write(fd, &ahdiboot, sizeof(ahdiboot))
    400 							!= sizeof(ahdiboot))
    401 				err(EXIT_FAILURE, "%s", devnm);
    402 			if (verbose)
    403 				printf("AHDI root  installed on %s (sector 0)\n",
    404 									devnm);
    405 		}
    406 		if (close(fd))
    407 			err(EXIT_FAILURE, "%s", devnm);
    408 	}
    409 }
    410 
    411 static void
    412 mkahdiboot (newroot, xxb00t, devnm, bbsec)
    413 	struct ahdi_root *newroot;
    414 	char		 *xxb00t,
    415 			 *devnm;
    416 	daddr_t		 bbsec;
    417 {
    418 	struct ahdi_root tmproot;
    419 	struct ahdi_part *pd;
    420 	int		 fd;
    421 
    422 	/* read prototype root-sector */
    423 	if ((fd = open(xxb00t, O_RDONLY)) < 0)
    424 		err(EXIT_FAILURE, "%s", xxb00t);
    425 	if (read(fd, &tmproot, sizeof(tmproot)) != sizeof(tmproot))
    426 		err(EXIT_FAILURE, "%s", xxb00t);
    427 	if (close(fd))
    428 		err(EXIT_FAILURE, "%s", xxb00t);
    429 
    430 	/* set tracks/cylinder and sectors/track */
    431 	setIDEpar(tmproot.ar_fill, sizeof(tmproot.ar_fill));
    432 
    433 	/* read current root-sector */
    434 	if ((fd = open(devnm, O_RDONLY)) < 0)
    435 		err(EXIT_FAILURE, "%s", devnm);
    436 	if (read(fd, newroot, sizeof(*newroot)) != sizeof(*newroot))
    437 		err(EXIT_FAILURE, "%s", devnm);
    438 	if (close(fd))
    439 		err(EXIT_FAILURE, "%s", devnm);
    440 
    441 	/* set bootflags */
    442 	for (pd = newroot->ar_parts; pd-newroot->ar_parts < AHDI_MAXRPD; ++pd) {
    443 		if (pd->ap_st == bbsec) {
    444 			pd->ap_flg = 0x21;	/* bootable, pref = NetBSD */
    445 			goto gotit;
    446 		}
    447 	}
    448 	errx(EXIT_FAILURE,
    449 	     "%s: NetBSD boot block not on primary AHDI partition.", devnm);
    450 
    451 gotit:	/* copy code from prototype and set new checksum */
    452 	memcpy(newroot->ar_fill, tmproot.ar_fill, sizeof(tmproot.ar_fill));
    453 	newroot->ar_checksum = 0;
    454 	newroot->ar_checksum = 0x1234 - abcksum(newroot);
    455 
    456 	if (verbose)
    457 		printf("AHDI      boot loader: %s\n", xxb00t);
    458 }
    459 
    460 static void
    461 mkbootblock (bb, xxb, bxx, label, magic)
    462 	struct bootblock *bb;
    463 	char		 *xxb,
    464 			 *bxx;
    465 	u_int		 magic;
    466 	struct disklabel *label;
    467 {
    468 	int		 fd;
    469 
    470 	memset(bb, 0, sizeof(*bb));
    471 
    472 	/* set boot block magic */
    473 	bb->bb_magic = magic;
    474 
    475 	/* set disk pack label */
    476 	BBSETLABEL(bb, label);
    477 
    478 	/* set second-stage boot loader */
    479 	if ((fd = open(bxx, O_RDONLY)) < 0)
    480 		err(EXIT_FAILURE, "%s", bxx);
    481 	if (read(fd, bb->bb_bootxx, sizeof(bb->bb_bootxx))
    482 					!= sizeof(bb->bb_bootxx))
    483 		err(EXIT_FAILURE, "%s", bxx);
    484 	if (close(fd))
    485 		err(EXIT_FAILURE, "%s", bxx);
    486 
    487 	/* set first-stage bootloader */
    488 	if ((fd = open(xxb, O_RDONLY)) < 0)
    489 		err(EXIT_FAILURE, "%s", xxb);
    490 	if (read(fd, bb->bb_xxboot, sizeof(bb->bb_xxboot))
    491 					!= sizeof(bb->bb_xxboot))
    492 		err(EXIT_FAILURE, "%s", xxb);
    493 	if (close(fd))
    494 		err(EXIT_FAILURE, "%s", xxb);
    495 
    496 	/* set tracks/cylinder and sectors/track */
    497 	setIDEpar(bb->bb_xxboot, sizeof(bb->bb_xxboot));
    498 
    499 	/* set AHDI checksum */
    500 	*((u_int16_t *)bb->bb_xxboot + 255) = 0;
    501 	*((u_int16_t *)bb->bb_xxboot + 255) = 0x1234 - abcksum(bb->bb_xxboot);
    502 
    503 	if (verbose) {
    504 		printf("Primary   boot loader: %s\n", xxb);
    505 		printf("Secondary boot loader: %s\n", bxx);
    506 	}
    507 }
    508 
    509 static void
    510 setIDEpar (start, size)
    511 	u_int8_t	*start;
    512 	size_t		size;
    513 {
    514 	static const u_int8_t	mark[] = { 'N', 'e', 't', 'B', 'S', 'D' };
    515 
    516 	if ((u_int)trackpercyl > 255)
    517 		errx(EXIT_FAILURE,
    518 		     "%d: Illegal tracks/cylinder value (1..255)", trackpercyl);
    519 	if ((u_int)secpertrack > 255)
    520 		errx(EXIT_FAILURE,
    521 		     "%d: Illegal sectors/track value (1..255)", secpertrack);
    522 
    523 	if (trackpercyl || secpertrack) {
    524 		u_int8_t *p;
    525 
    526 		if (!trackpercyl)
    527 			errx(EXIT_FAILURE, "Need tracks/cylinder too.");
    528 		if (!secpertrack)
    529 			errx(EXIT_FAILURE, "Need sectors/track too.");
    530 
    531 		start += 2;
    532 		size  -= sizeof(mark) + 2;
    533 		for (p = start + size; p >= start; --p) {
    534 			if (*p != *mark)
    535 				continue;
    536 			if (!memcmp(p, mark, sizeof(mark)))
    537 				break;
    538 		}
    539 		if (p < start)
    540 			errx(EXIT_FAILURE,
    541 			     "Malformatted xxboot prototype.");
    542 
    543 		*--p = secpertrack;
    544 		*--p = trackpercyl;
    545 
    546 		if (verbose) {
    547 			printf("sectors/track  : %d\n", secpertrack);
    548 			printf("tracks/cylinder: %d\n", trackpercyl);
    549 		}
    550 	}
    551 }
    552 
    553 static void
    554 setNVpref ()
    555 {
    556 	static const u_char	bootpref = BOOTPREF_NETBSD;
    557 	static const char	nvrdev[] = PATH_NVRAM;
    558 
    559 	if (!nowrite) {
    560 		int	fd;
    561 
    562 		if ((fd = open(nvrdev, O_RDWR)) < 0)
    563 			err(EXIT_FAILURE, "%s", nvrdev);
    564 		if (lseek(fd, (off_t)1, SEEK_SET) != 1)
    565 			err(EXIT_FAILURE, "%s", nvrdev);
    566 		if (write(fd, &bootpref, (size_t)1) != 1)
    567 			err(EXIT_FAILURE, "%s", nvrdev);
    568 		if (close(fd))
    569 			err(EXIT_FAILURE, "%s", nvrdev);
    570 		if (verbose)
    571 			printf("Boot preference set to NetBSD.\n");
    572 	}
    573 }
    574 
    575 static u_int
    576 abcksum (bs)
    577 	void	*bs;
    578 {
    579 	u_int16_t sum  = 0,
    580 		  *st  = (u_int16_t *)bs,
    581 		  *end = (u_int16_t *)bs + 256;
    582 
    583 	while (st < end)
    584 		sum += *st++;
    585 	return(sum);
    586 }
    587