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