Home | History | Annotate | Line # | Download | only in installboot
installboot.c revision 1.2
      1 /*	$NetBSD: installboot.c,v 1.2 1996/03/28 21:53:35 leo 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 
     46 /*
     47  * Small reminder for myself ;-)
     48  */
     49 #if NetBSD != 199511
     50 #error New NetBSD version! Update OS_LIST in installboot.h
     51 #endif
     52 
     53 #define	DKTYPENAMES
     54 #include <sys/disklabel.h>
     55 #include <machine/ahdilabel.h>
     56 
     57 #include "installboot.h"
     58 
     59 static void	usage __P((void));
     60 static void	oscheck __P((void));
     61 static u_int	abcksum __P((void *));
     62 static void	setNVpref __P((void));
     63 static void	setIDEpar __P((u_int8_t *, size_t));
     64 static void	mkahdiboot __P((struct ahdi_root *, char *,
     65 						char *, daddr_t));
     66 static void	mkbootblock __P((struct bootblock *, char *,
     67 				char *, struct disklabel *, u_int));
     68 static void	install_fd __P((char *, struct disklabel *));
     69 static void	install_sd __P((char *, struct disklabel *));
     70 static void	install_wd __P((char *, struct disklabel *));
     71 
     72 static struct bootblock	bootarea;
     73 static struct ahdi_root ahdiboot;
     74 static const char	mdecpath[] = PATH_MDEC;
     75 static int		nowrite = 0;
     76 static int		verbose = 0;
     77 static int		trackpercyl = 0;
     78 static int		secpertrack = 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-t  number of tracks per cylinder (IDE disk)\n"
     88 		"\t-u  number of sectors per track (IDE disk)\n"
     89 		"\t-v  verbose mode\n");
     90 	exit(EXIT_FAILURE);
     91 }
     92 
     93 int
     94 main (argc, argv)
     95 	int	argc;
     96 	char	*argv[];
     97 {
     98 	struct disklabel dl;
     99 	char		 *dn;
    100 	int		 fd, c;
    101 
    102 	/* check OS type, release and revision */
    103 	oscheck();
    104 
    105 	/* parse options */
    106 	while ((c = getopt(argc, argv, "Nt:u:v")) != -1) {
    107 		switch (c) {
    108 		  case 'N':
    109 			nowrite = 1;
    110 			break;
    111 		  case 't':
    112 			trackpercyl = atoi(optarg);
    113 			break;
    114 		  case 'u':
    115 			secpertrack = atoi(optarg);
    116 			break;
    117 		  case 'v':
    118 			verbose = 1;
    119 			break;
    120 		  default:
    121 			usage();
    122 		}
    123 	}
    124 	argv += optind;
    125 	argc -= optind;
    126 	if (argc != 1)
    127 		usage();
    128 
    129 	/* get disk label */
    130 	dn = alloca(sizeof(_PATH_DEV) + strlen(argv[0]) + 8);
    131 	if (!strchr(argv[0], '/')) {
    132 		sprintf(dn, "%sr%s%c", _PATH_DEV, argv[0], RAW_PART + 'a');
    133 		fd = open(dn, O_RDONLY);
    134 		if (fd < 0 && errno == ENOENT) {
    135 			sprintf(dn, "%sr%s", _PATH_DEV, argv[0]);
    136 			fd = open(dn, O_RDONLY);
    137 		}
    138 	} else {
    139 		sprintf(dn, "%s", argv[0]);
    140 		fd = open(dn, O_RDONLY);
    141 	}
    142 	if (fd < 0)
    143 		err(EXIT_FAILURE, "%s", dn);
    144 	if (ioctl(fd, DIOCGDINFO, &dl))
    145 		err(EXIT_FAILURE, "%s: DIOCGDINFO", dn);
    146 	if (close(fd))
    147 		err(EXIT_FAILURE, "%s", dn);
    148 
    149 	switch (dl.d_type) {
    150 		case DTYPE_FLOPPY:
    151 			install_fd(dn, &dl);
    152 			break;
    153 		case DTYPE_ST506:
    154 			install_wd(dn, &dl);
    155 			setNVpref();
    156 			break;
    157 		case DTYPE_SCSI:
    158 			install_sd(dn, &dl);
    159 			setNVpref();
    160 			break;
    161 		default:
    162 			errx(EXIT_FAILURE,
    163 			     "%s: %s: Device type not supported.",
    164 			     dn, dktypenames[dl.d_type]);
    165 	}
    166 
    167 	return(EXIT_SUCCESS);
    168 }
    169 
    170 static char *
    171 lststr (lst, str, bra)
    172 	char	*lst, *str, *bra;
    173 {
    174 	char	*p;
    175 
    176 	while ((p = strchr(lst, bra[0])) != NULL) {
    177 		lst = strchr(++p, bra[1]);
    178 		if (strncmp(str, p, lst - p))
    179 			continue;
    180 		if ((p = strchr(lst, bra[0])))
    181 			*p = 0;
    182 		return(++lst);
    183 	}
    184 	return(NULL);
    185 }
    186 
    187 static void
    188 oscheck ()
    189 {
    190 	/* ideally, this would be a nested function... */
    191 	static char *lststr __P((char *, char *, char *));
    192 	static const char os_list[] = OS_LIST;
    193 
    194 	char	*list, *type, *rel, *rev;
    195 	int	mib[2], rvi;
    196 	size_t	len;
    197 
    198 	list = alloca(sizeof(os_list));
    199 	strcpy(list, os_list);
    200 
    201 	mib[0] = CTL_KERN;
    202 	mib[1] = KERN_OSTYPE;
    203 	sysctl(mib, 2, NULL, &len, NULL, 0);
    204 	type = alloca(len);
    205 	sysctl(mib, 2, type, &len, NULL, 0);
    206 	if ((list = lststr(list, type, BRA_TYPE)) == NULL)
    207 		errx(EXIT_FAILURE,
    208 		     "%s: OS type not supported", type);
    209 
    210 	mib[0] = CTL_KERN;
    211 	mib[1] = KERN_OSRELEASE;
    212 	sysctl(mib, 2, NULL, &len, NULL, 0);
    213 	rel = alloca(len);
    214 	sysctl(mib, 2, rel, &len, NULL, 0);
    215 	if ((list = lststr(list, rel, BRA_RELEASE)) == NULL)
    216 		errx(EXIT_FAILURE,
    217 		     "%s %s: OS release not supported", type, rel);
    218 
    219 	mib[0] = CTL_KERN;
    220 	mib[1] = KERN_OSREV;
    221 	len = sizeof(rvi);
    222 	sysctl(mib, 2, &rvi, &len, NULL, 0);
    223 	rev = alloca(3 * sizeof(rvi));
    224 	sprintf(rev, "%u", rvi);
    225 	if ((list = lststr(list, rev, BRA_REVISION)) == NULL)
    226 		errx(EXIT_FAILURE,
    227 		     "%s %s %s: OS revision not supported", type, rel, rev);
    228 }
    229 
    230 static void
    231 install_fd (devnm, label)
    232 	char		 *devnm;
    233 	struct disklabel *label;
    234 {
    235 	char		 *xxboot, *bootxx;
    236 	struct partition *rootpart;
    237 
    238 	if (label->d_secsize != 512)
    239 		errx(EXIT_FAILURE,
    240 		     "%s: %u: Block size not supported.", devnm,
    241 							  label->d_secsize);
    242 	if (label->d_ntracks != 2)
    243 		errx(EXIT_FAILURE,
    244 		     "%s: Single sided floppy not supported.", devnm);
    245 
    246 	xxboot = alloca(strlen(mdecpath) + 8);
    247 	sprintf(xxboot, "%sfdboot", mdecpath);
    248 	bootxx = alloca(strlen(mdecpath) + 8);
    249 	sprintf(bootxx, "%sbootxx", mdecpath);
    250 
    251 	/* first used partition (a, b or c) */		/* XXX */
    252 	for (rootpart = label->d_partitions; ; ++rootpart) {
    253 		if (rootpart->p_size)
    254 			break;
    255 	}
    256 	if (rootpart != label->d_partitions) {		/* XXX */
    257 		*(label->d_partitions) = *rootpart;
    258 		memset(rootpart, 0, sizeof(*rootpart));
    259 	}
    260 	label->d_partitions->p_fstype = FS_BSDFFS;	/* XXX */
    261 	label->d_npartitions = 1;
    262 	label->d_checksum = 0;
    263 	label->d_checksum = dkcksum(label);
    264 
    265 	trackpercyl = secpertrack = 0;
    266 	mkbootblock(&bootarea, xxboot, bootxx, label, 0);
    267 
    268 	if (!nowrite) {
    269 		int	fd;
    270 		if ((fd = open(devnm, O_WRONLY)) < 0)
    271 			err(EXIT_FAILURE, "%s", devnm);
    272 		if (write(fd, &bootarea, sizeof(bootarea)) != sizeof(bootarea))
    273 			err(EXIT_FAILURE, "%s", devnm);
    274 		if (close(fd))
    275 			err(EXIT_FAILURE, "%s", devnm);
    276 		if (verbose)
    277 			printf("Boot block installed on %s\n", devnm);
    278 	}
    279 }
    280 
    281 static void
    282 install_sd (devnm, label)
    283 	char		 *devnm;
    284 	struct disklabel *label;
    285 {
    286 	char		 *xxb00t, *xxboot, *bootxx;
    287 	struct disklabel rawlabel;
    288 	daddr_t		 bbsec;
    289 	u_int		 magic;
    290 
    291 	if (label->d_partitions[0].p_size == 0)
    292 		errx(EXIT_FAILURE, "%s: No root-filesystem.", devnm);
    293 	if (label->d_partitions[0].p_fstype != FS_BSDFFS)
    294 		errx(EXIT_FAILURE, "%s: %s: Illegal root-filesystem type.",
    295 		     devnm, fstypenames[label->d_partitions[0].p_fstype]);
    296 
    297 	bbsec = readdisklabel(devnm, &rawlabel);
    298 	if (bbsec == NO_BOOT_BLOCK)
    299 		errx(EXIT_FAILURE, "%s: No NetBSD boot block.", devnm);
    300 	if (memcmp(label, &rawlabel, sizeof(*label)))
    301 		errx(EXIT_FAILURE, "%s: Invalid NetBSD boot block.", devnm);
    302 
    303 	if (bbsec) {
    304 		xxb00t = alloca(strlen(mdecpath) + 14);
    305 		sprintf(xxb00t, "%ssdb00t.ahdi", mdecpath);
    306 		xxboot = alloca(strlen(mdecpath) + 14);
    307 		sprintf(xxboot, "%sxxboot.ahdi", mdecpath);
    308 		magic = AHDIMAGIC;
    309 	} else {
    310 		xxb00t = NULL;
    311 		xxboot = alloca(strlen(mdecpath) + 8);
    312 		sprintf(xxboot, "%ssdboot", mdecpath);
    313 		magic = NBDAMAGIC;
    314 	}
    315 	bootxx = alloca(strlen(mdecpath) + 8);
    316 	sprintf(bootxx, "%sbootxx", mdecpath);
    317 
    318 	trackpercyl = secpertrack = 0;
    319 	if (xxb00t)
    320 		mkahdiboot(&ahdiboot, xxb00t, devnm, bbsec);
    321 	mkbootblock(&bootarea, xxboot, bootxx, label, magic);
    322 
    323 	if (!nowrite) {
    324 		off_t	bbo = bbsec * AHDI_BSIZE;
    325 		int	fd;
    326 
    327 		if ((fd = open(devnm, O_WRONLY)) < 0)
    328 			err(EXIT_FAILURE, "%s", devnm);
    329 		if (lseek(fd, bbo, SEEK_SET) != bbo)
    330 			err(EXIT_FAILURE, "%s", devnm);
    331 		if (write(fd, &bootarea, sizeof(bootarea)) != sizeof(bootarea))
    332 			err(EXIT_FAILURE, "%s", devnm);
    333 		if (verbose)
    334 			printf("Boot block installed on %s (%u)\n", devnm,
    335 								    bbsec);
    336 		if (xxb00t) {
    337 			if (lseek(fd, (off_t)0, SEEK_SET) != 0)
    338 				err(EXIT_FAILURE, "%s", devnm);
    339 			if (write(fd, &ahdiboot, sizeof(ahdiboot)) != sizeof(ahdiboot))
    340 				err(EXIT_FAILURE, "%s", devnm);
    341 			if (verbose)
    342 				printf("AHDI root  installed on %s (0)\n",
    343 								devnm);
    344 		}
    345 		if (close(fd))
    346 			err(EXIT_FAILURE, "%s", devnm);
    347 	}
    348 }
    349 
    350 static void
    351 install_wd (devnm, label)
    352 	char		 *devnm;
    353 	struct disklabel *label;
    354 {
    355 	char		 *xxb00t, *xxboot, *bootxx;
    356 	struct disklabel rawlabel;
    357 	daddr_t		 bbsec;
    358 	u_int		 magic;
    359 
    360 	if (label->d_partitions[0].p_size == 0)
    361 		errx(EXIT_FAILURE, "%s: No root-filesystem.", devnm);
    362 	if (label->d_partitions[0].p_fstype != FS_BSDFFS)
    363 		errx(EXIT_FAILURE, "%s: %s: Illegal root-filesystem type.",
    364 		     devnm, fstypenames[label->d_partitions[0].p_fstype]);
    365 
    366 	bbsec = readdisklabel(devnm, &rawlabel);
    367 	if (bbsec == NO_BOOT_BLOCK)
    368 		errx(EXIT_FAILURE, "%s: No NetBSD boot block.", devnm);
    369 	if (memcmp(label, &rawlabel, sizeof(*label)))
    370 		errx(EXIT_FAILURE, "%s: Invalid NetBSD boot block.", devnm);
    371 
    372 	if (bbsec) {
    373 		xxb00t = alloca(strlen(mdecpath) + 14);
    374 		sprintf(xxb00t, "%swdb00t.ahdi", mdecpath);
    375 		xxboot = alloca(strlen(mdecpath) + 14);
    376 		sprintf(xxboot, "%sxxboot.ahdi", mdecpath);
    377 		magic = AHDIMAGIC;
    378 	} else {
    379 		xxb00t = NULL;
    380 		xxboot = alloca(strlen(mdecpath) + 8);
    381 		sprintf(xxboot, "%swdboot", mdecpath);
    382 		magic = NBDAMAGIC;
    383 	}
    384 	bootxx = alloca(strlen(mdecpath) + 8);
    385 	sprintf(bootxx, "%sbootxx", mdecpath);
    386 
    387 	if (xxb00t)
    388 		mkahdiboot(&ahdiboot, xxb00t, devnm, bbsec);
    389 	mkbootblock(&bootarea, xxboot, bootxx, label, magic);
    390 
    391 	if (!nowrite) {
    392 		int	fd;
    393 		off_t	bbo;
    394 
    395 		bbo = bbsec * AHDI_BSIZE;
    396 		if ((fd = open(devnm, O_WRONLY)) < 0)
    397 			err(EXIT_FAILURE, "%s", devnm);
    398 		if (lseek(fd, bbo, SEEK_SET) != bbo)
    399 			err(EXIT_FAILURE, "%s", devnm);
    400 		if (write(fd, &bootarea, sizeof(bootarea)) != sizeof(bootarea))
    401 			err(EXIT_FAILURE, "%s", devnm);
    402 		if (verbose)
    403 			printf("Boot block installed on %s (%u)\n", devnm,
    404 								    bbsec);
    405 		if (xxb00t) {
    406 			if (lseek(fd, (off_t)0, SEEK_SET) != 0)
    407 				err(EXIT_FAILURE, "%s", devnm);
    408 			if (write(fd, &ahdiboot, sizeof(ahdiboot))
    409 							!= sizeof(ahdiboot))
    410 				err(EXIT_FAILURE, "%s", devnm);
    411 			if (verbose)
    412 				printf("AHDI root  installed on %s (0)\n",
    413 									devnm);
    414 		}
    415 		if (close(fd))
    416 			err(EXIT_FAILURE, "%s", devnm);
    417 	}
    418 }
    419 
    420 static void
    421 mkahdiboot (newroot, xxb00t, devnm, bbsec)
    422 	struct ahdi_root *newroot;
    423 	char		 *xxb00t,
    424 			 *devnm;
    425 	daddr_t		 bbsec;
    426 {
    427 	struct ahdi_root tmproot;
    428 	struct ahdi_part *pd;
    429 	int		 fd;
    430 
    431 	/* read prototype root-sector */
    432 	if ((fd = open(xxb00t, O_RDONLY)) < 0)
    433 		err(EXIT_FAILURE, "%s", xxb00t);
    434 	if (read(fd, &tmproot, sizeof(tmproot)) != sizeof(tmproot))
    435 		err(EXIT_FAILURE, "%s", xxb00t);
    436 	if (close(fd))
    437 		err(EXIT_FAILURE, "%s", xxb00t);
    438 
    439 	/* set tracks/cylinder and sectors/track */
    440 	setIDEpar(tmproot.ar_fill, sizeof(tmproot.ar_fill));
    441 
    442 	/* read current root-sector */
    443 	if ((fd = open(devnm, O_RDONLY)) < 0)
    444 		err(EXIT_FAILURE, "%s", devnm);
    445 	if (read(fd, newroot, sizeof(*newroot)) != sizeof(*newroot))
    446 		err(EXIT_FAILURE, "%s", devnm);
    447 	if (close(fd))
    448 		err(EXIT_FAILURE, "%s", devnm);
    449 
    450 	/* set bootflags */
    451 	for (pd = newroot->ar_parts; pd-newroot->ar_parts < AHDI_MAXRPD; ++pd) {
    452 		if (pd->ap_st == bbsec) {
    453 			pd->ap_flg = 0x21;	/* bootable, pref = NetBSD */
    454 			goto gotit;
    455 		}
    456 	}
    457 	errx(EXIT_FAILURE,
    458 	     "%s: NetBSD boot block not on primary AHDI partition.", devnm);
    459 
    460 gotit:	/* copy code from prototype and set new checksum */
    461 	memcpy(newroot->ar_fill, tmproot.ar_fill, sizeof(tmproot.ar_fill));
    462 	newroot->ar_checksum = 0;
    463 	newroot->ar_checksum = 0x1234 - abcksum(newroot);
    464 
    465 	if (verbose)
    466 		printf("AHDI      boot loader: %s\n", xxb00t);
    467 }
    468 
    469 static void
    470 mkbootblock (bb, xxb, bxx, label, magic)
    471 	struct bootblock *bb;
    472 	char		 *xxb,
    473 			 *bxx;
    474 	u_int		 magic;
    475 	struct disklabel *label;
    476 {
    477 	int		 fd;
    478 
    479 	memset(bb, 0, sizeof(*bb));
    480 
    481 	/* set boot block magic */
    482 	bb->bb_magic = magic;
    483 
    484 	/* set disk pack label */
    485 	BBSETLABEL(bb, label);
    486 
    487 	/* set second-stage boot loader */
    488 	if ((fd = open(bxx, O_RDONLY)) < 0)
    489 		err(EXIT_FAILURE, "%s", bxx);
    490 	if (read(fd, bb->bb_bootxx, sizeof(bb->bb_bootxx))
    491 					!= sizeof(bb->bb_bootxx))
    492 		err(EXIT_FAILURE, "%s", bxx);
    493 	if (close(fd))
    494 		err(EXIT_FAILURE, "%s", bxx);
    495 
    496 	/* set first-stage bootloader */
    497 	if ((fd = open(xxb, O_RDONLY)) < 0)
    498 		err(EXIT_FAILURE, "%s", xxb);
    499 	if (read(fd, bb->bb_xxboot, sizeof(bb->bb_xxboot))
    500 					!= sizeof(bb->bb_xxboot))
    501 		err(EXIT_FAILURE, "%s", xxb);
    502 	if (close(fd))
    503 		err(EXIT_FAILURE, "%s", xxb);
    504 
    505 	/* set tracks/cylinder and sectors/track */
    506 	setIDEpar(bb->bb_xxboot, sizeof(bb->bb_xxboot));
    507 
    508 	/* set AHDI checksum */
    509 	*((u_int16_t *)bb->bb_xxboot + 255) = 0;
    510 	*((u_int16_t *)bb->bb_xxboot + 255) = 0x1234 - abcksum(bb->bb_xxboot);
    511 
    512 	if (verbose) {
    513 		printf("Primary   boot loader: %s\n", xxb);
    514 		printf("Secondary boot loader: %s\n", bxx);
    515 	}
    516 }
    517 
    518 static void
    519 setIDEpar (start, size)
    520 	u_int8_t	*start;
    521 	size_t		size;
    522 {
    523 	static const u_int8_t	mark[] = { 'N', 'e', 't', 'B', 'S', 'D' };
    524 
    525 	if ((u_int)trackpercyl > 255)
    526 		errx(EXIT_FAILURE,
    527 		     "%d: Illegal tracks/cylinder value (1..255)", trackpercyl);
    528 	if ((u_int)secpertrack > 255)
    529 		errx(EXIT_FAILURE,
    530 		     "%d: Illegal sectors/track value (1..255)", secpertrack);
    531 
    532 	if (trackpercyl || secpertrack) {
    533 		u_int8_t *p;
    534 
    535 		if (!trackpercyl)
    536 			errx(EXIT_FAILURE, "Need tracks/cylinder too.");
    537 		if (!secpertrack)
    538 			errx(EXIT_FAILURE, "Need sectors/track too.");
    539 
    540 		start += 2;
    541 		size  -= sizeof(mark) + 2;
    542 		for (p = start + size; p >= start; --p) {
    543 			if (*p != *mark)
    544 				continue;
    545 			if (!memcmp(p, mark, sizeof(mark)))
    546 				break;
    547 		}
    548 		if (p < start)
    549 			errx(EXIT_FAILURE,
    550 			     "Malformatted xxboot prototype.");
    551 
    552 		*--p = secpertrack;
    553 		*--p = trackpercyl;
    554 
    555 		if (verbose) {
    556 			printf("sectors/track  : %d\n", secpertrack);
    557 			printf("tracks/cylinder: %d\n", trackpercyl);
    558 		}
    559 	}
    560 }
    561 
    562 static void
    563 setNVpref ()
    564 {
    565 	static const u_char	bootpref = BOOTPREF_NETBSD;
    566 	static const char	nvrdev[] = PATH_NVRAM;
    567 
    568 	if (!nowrite) {
    569 		int	fd;
    570 
    571 		if ((fd = open(nvrdev, O_RDWR)) < 0)
    572 			err(EXIT_FAILURE, "%s", nvrdev);
    573 		if (lseek(fd, (off_t)1, SEEK_SET) != 1)
    574 			err(EXIT_FAILURE, "%s", nvrdev);
    575 		if (write(fd, &bootpref, (size_t)1) != 1)
    576 			err(EXIT_FAILURE, "%s", nvrdev);
    577 		if (close(fd))
    578 			err(EXIT_FAILURE, "%s", nvrdev);
    579 		if (verbose)
    580 			printf("Boot preference set to NetBSD.\n");
    581 	}
    582 }
    583 
    584 static u_int
    585 abcksum (bs)
    586 	void	*bs;
    587 {
    588 	u_int16_t sum  = 0,
    589 		  *st  = (u_int16_t *)bs,
    590 		  *end = (u_int16_t *)bs + 256;
    591 
    592 	while (st < end)
    593 		sum += *st++;
    594 	return(sum);
    595 }
    596