usr.bin/man src/usr.bin/man
usr.bin/apropos src/usr.bin/apropos
usr.bin/mdocml src/external/bsd/mdocml
+usr.sbin/installboot src/usr.sbin/installboot
usr.sbin/pwd_mkdb src/usr.sbin/pwd_mkdb
usr.sbin/user src/usr.sbin/user
usr.sbin/vipw src/usr.sbin/vipw
--- /dev/null
+# $NetBSD: Makefile,v 1.46 2011/08/14 17:50:16 christos Exp $
+#
+
+.include <bsd.own.mk>
+
+PROG= installboot
+MAN= installboot.8
+SRCS= installboot.c sum.c machines.c fstypes.c
+
+
+ARCH_XLAT= amd64-i386.c news68k-news.c newsmips-news.c
+ARCH_XLAT+= sun2-sun68k.c sun3-sun68k.c
+
+.if !defined(SMALLPROG) && !defined(ARCH_FILES)
+ARCH_FILES= alpha.c amiga.c emips.c ews4800mips.c hp300.c hp700.c i386.c
+ARCH_FILES+= landisk.c macppc.c news.c next68k.c pmax.c
+ARCH_FILES+= sparc.c sparc64.c sun68k.c vax.c x68k.c
+.else
+ARCH_FILES?= ${ARCH_XLAT:M${MACHINE}-*:S/${MACHINE}-//}
+.if empty(ARCH_FILES)
+ARCH_FILES= ${MACHINE}.c
+.endif
+.endif
+
+SRCS+=${ARCH_FILES}
+
+.if empty(ARCH_FILES:C/(macppc|news|sparc|sun68k|x68k)/stg2/:Mstg2.c)
+CPPFLAGS += -DNO_STAGE2
+.else
+SRCS+= bbinfo.c
+
+# fstypes are only needed for 'stage2' and then only from bbinfo.
+SRCS+= ffs.c
+.if SMALLPROG
+CPPFLAGS+= -DNO_FFS_SWAP
+.else
+SRCS+= ffs_bswap.c
+.endif
+#SRCS+= ext2fs.c ext2fs_bswap.c
+.endif
+
+UFSSRC= ${NETBSDSRCDIR}/sys/ufs
+CPPFLAGS+= -I${.CURDIR} -I.
+.PATH: ${.CURDIR}/arch ${UFSSRC}/ffs ${UFSSRC}/ext2fs
+
+.if !defined(HOSTPROGNAME)
+.if defined(HAVE_GCC) || defined(HAVE_PCC)
+.for f in i386 macppc
+COPTS.${f}.c+= -Wno-pointer-sign
+.endfor
+.endif
+.endif
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: alpha.c,v 1.21 2011/08/14 17:50:17 christos Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Ross Harvey. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ross Harvey
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: alpha.c,v 1.21 2011/08/14 17:50:17 christos Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+#define SUN_DKMAGIC 55998 /* XXX: from <dev/sun/disklabel.h> */
+
+static void resum(ib_params *, struct alpha_boot_block * const bb,
+ uint16_t *bb16);
+static void sun_bootstrap(ib_params *, struct alpha_boot_block * const);
+static void check_sparc(const struct alpha_boot_block * const,
+ const char *);
+
+static int alpha_clearboot(ib_params *);
+static int alpha_setboot(ib_params *);
+
+struct ib_mach ib_mach_alpha =
+ { "alpha", alpha_setboot, alpha_clearboot, no_editboot,
+ IB_STAGE1START | IB_ALPHASUM | IB_APPEND | IB_SUNSUM };
+
+static int
+alpha_clearboot(ib_params *params)
+{
+ struct alpha_boot_block bb;
+ uint64_t cksum;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(sizeof(struct alpha_boot_block) == ALPHA_BOOT_BLOCK_BLOCKSIZE);
+
+ if (params->flags & (IB_STAGE1START | IB_APPEND)) {
+ warnx("Can't use `-b bno' or `-o append' with `-c'");
+ return (0);
+ }
+
+ rv = pread(params->fsfd, &bb, sizeof(bb), ALPHA_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ return (0);
+ }
+ ALPHA_BOOT_BLOCK_CKSUM(&bb, &cksum);
+ if (cksum != bb.bb_cksum) { // XXX check bb_cksum endian?
+ warnx(
+ "Old boot block checksum invalid (was %#llx, calculated %#llx)",
+ (unsigned long long)le64toh(bb.bb_cksum),
+ (unsigned long long)le64toh(cksum));
+ warnx("Boot block invalid");
+ return (0);
+ }
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Old bootstrap start sector: %llu\n",
+ (unsigned long long)le64toh(bb.bb_secstart));
+ printf("Old bootstrap size: %llu\n",
+ (unsigned long long)le64toh(bb.bb_secsize));
+ printf("Old bootstrap checksum: %#llx\n",
+ (unsigned long long)le64toh(bb.bb_cksum));
+ }
+
+ bb.bb_secstart = bb.bb_secsize = bb.bb_flags = 0;
+
+ ALPHA_BOOT_BLOCK_CKSUM(&bb, &bb.bb_cksum);
+ if (params->flags & IB_SUNSUM)
+ sun_bootstrap(params, &bb);
+
+ printf("New bootstrap start sector: %llu\n",
+ (unsigned long long)le64toh(bb.bb_secstart));
+ printf("New bootstrap size: %llu\n",
+ (unsigned long long)le64toh(bb.bb_secsize));
+ printf("New bootstrap checksum: %#llx\n",
+ (unsigned long long)le64toh(bb.bb_cksum));
+
+ if (params->flags & IB_VERBOSE)
+ printf("%slearing boot block\n",
+ (params->flags & IB_NOWRITE) ? "Not c" : "C");
+ if (params->flags & IB_NOWRITE)
+ return (1);
+
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), ALPHA_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+alpha_setboot(ib_params *params)
+{
+ struct alpha_boot_block bb;
+ uint64_t startblock;
+ int retval;
+ char *bootstrapbuf;
+ size_t bootstrapsize;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+ assert(sizeof(struct alpha_boot_block) == ALPHA_BOOT_BLOCK_BLOCKSIZE);
+
+ retval = 0;
+ bootstrapbuf = NULL;
+
+ /*
+ * Allocate a buffer, with space to round up the input file
+ * to the next block size boundary, and with space for the boot
+ * block.
+ */
+ bootstrapsize = roundup(params->s1stat.st_size,
+ ALPHA_BOOT_BLOCK_BLOCKSIZE);
+
+ bootstrapbuf = malloc(bootstrapsize);
+ if (bootstrapbuf == NULL) {
+ warn("Allocating %lu bytes", (unsigned long) bootstrapsize);
+ goto done;
+ }
+ memset(bootstrapbuf, 0, bootstrapsize);
+
+ /* read the file into the buffer */
+ rv = pread(params->s1fd, bootstrapbuf, params->s1stat.st_size, 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ } else if (rv != params->s1stat.st_size) {
+ warnx("Reading `%s': short read", params->stage1);
+ goto done;
+ }
+
+ rv = pread(params->fsfd, &bb, sizeof(bb), ALPHA_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ if (params->flags & IB_SUNSUM)
+ check_sparc(&bb, "Initial");
+
+ /* fill in the updated bootstrap fields */
+ if (params->flags & IB_APPEND) {
+ struct stat filesyssb;
+
+ if (fstat(params->fsfd, &filesyssb) == -1) {
+ warn("Examining `%s'", params->filesystem);
+ goto done;
+ }
+ if (!S_ISREG(filesyssb.st_mode)) {
+ warnx(
+ "`%s' must be a regular file to append a bootstrap",
+ params->filesystem);
+ goto done;
+ }
+ startblock = howmany(filesyssb.st_size,
+ ALPHA_BOOT_BLOCK_BLOCKSIZE);
+ } else if (params->flags & IB_STAGE1START) {
+ startblock = params->s1start;
+ } else {
+ startblock = ALPHA_BOOT_BLOCK_OFFSET /
+ ALPHA_BOOT_BLOCK_BLOCKSIZE + 1;
+ }
+
+ bb.bb_secsize =
+ htole64(howmany(params->s1stat.st_size,
+ ALPHA_BOOT_BLOCK_BLOCKSIZE));
+ bb.bb_secstart = htole64(startblock);
+ bb.bb_flags = 0;
+
+ ALPHA_BOOT_BLOCK_CKSUM(&bb, &bb.bb_cksum);
+ if (params->flags & IB_SUNSUM)
+ sun_bootstrap(params, &bb);
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %llu\n",
+ (unsigned long long)startblock);
+ printf("Bootstrap sector count: %llu\n",
+ (unsigned long long)le64toh(bb.bb_secsize));
+ printf("New boot block checksum: %#llx\n",
+ (unsigned long long)le64toh(bb.bb_cksum));
+ printf("%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+ rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
+ startblock * ALPHA_BOOT_BLOCK_BLOCKSIZE);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if ((size_t)rv != bootstrapsize) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE)
+ printf("Writing boot block\n");
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), ALPHA_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else {
+ retval = 1;
+ }
+
+ done:
+ if (bootstrapbuf)
+ free(bootstrapbuf);
+ return (retval);
+}
+
+
+/*
+ * The Sun and alpha checksums overlay, and the Sun magic number also
+ * overlays the alpha checksum. If you think you are smart: stop here
+ * and do exercise one: figure out how to salt unimportant uint16_t
+ * words in mid-sector so that the alpha and sparc checksums match,
+ * and so the Sun magic number is embedded in the alpha checksum.
+ *
+ * The last uint64_t in the sector is the alpha arithmetic checksum.
+ * The last uint16_t in the sector is the sun xor checksum.
+ * The penultimate uint16_t in the sector is the sun magic number.
+ *
+ * A: 511 510 509 508 507 506 505 504
+ * S: 510 511 508 509 506 507 504 505
+ * 63 : : : 32:31 : : : 0
+ * | : : : \:| : : : |
+ * 7654321076543210765432107654321076543210765432107654321076543210
+ * |-- sparc --||-- sparc --|
+ * |-- checksum --||-- magic --|
+ * |----------------------- alpha checksum -----------------------|
+ * 1011111011011010
+ * b e d a
+ */
+
+static void
+resum(ib_params *params, struct alpha_boot_block * const bb, uint16_t *bb16)
+{
+ static uint64_t lastsum;
+
+ if (bb16 != NULL)
+ memcpy(bb, bb16, sizeof(*bb));
+ ALPHA_BOOT_BLOCK_CKSUM(bb, &bb->bb_cksum);
+ if (bb16 != NULL)
+ memcpy(bb16, bb, sizeof(*bb));
+ if ((params->flags & IB_VERBOSE) && lastsum != bb->bb_cksum)
+ printf("alpha checksum now %016llx\n",
+ (unsigned long long)le64toh(bb->bb_cksum));
+ lastsum = bb->bb_cksum;
+}
+
+static void
+sun_bootstrap(ib_params *params, struct alpha_boot_block * const bb)
+{
+# define BB_ADJUST_OFFSET 64
+ static char our_int16s[] = "\2\3\6\7\12";
+ uint16_t i, j, chkdelta, sunsum, bb16[256];
+
+ /*
+ * Theory: the alpha checksum is adjusted so bits 47:32 add up
+ * to the Sun magic number. Then, another adjustment is computed
+ * so bits 63:48 add up to the Sun checksum, and applied in pieces
+ * so it changes the alpha checksum but not the Sun value.
+ *
+ * Note: using memcpy(3) instead of a union as a strict c89/c9x
+ * conformance experiment and to avoid a public interface delta.
+ */
+ assert(sizeof(bb16) == sizeof(*bb));
+ memcpy(bb16, bb, sizeof(bb16));
+ for (i = 0; our_int16s[i]; ++i) {
+ j = BB_ADJUST_OFFSET + our_int16s[i];
+ if (bb16[j]) {
+ warnx("Non-zero bits %04x in bytes %d..%d",
+ bb16[j], j * 2, j * 2 + 1);
+ bb16[j] = 0;
+ resum(params, bb, bb16);
+ }
+ }
+ /*
+ * Make alpha checksum <47:32> come out to the sun magic.
+ */
+ bb16[BB_ADJUST_OFFSET + 2] = htobe16(SUN_DKMAGIC) - bb16[254];
+ resum(params, bb, bb16);
+ sunsum = compute_sunsum(bb16); /* might be the final value */
+ if (params->flags & IB_VERBOSE)
+ printf("target sun checksum is %04x\n", sunsum);
+ /*
+ * Arrange to have alpha 63:48 add up to the sparc checksum.
+ */
+ chkdelta = sunsum - bb16[255];
+ bb16[BB_ADJUST_OFFSET + 3] = chkdelta >> 1;
+ bb16[BB_ADJUST_OFFSET + 7] = chkdelta >> 1;
+ /*
+ * By placing half the correction in two different uint64_t words at
+ * positions 63:48, the sparc sum will not change but the alpha sum
+ * will have the full correction, but only if the target adjustment
+ * was even. If it was odd, reverse propagate the carry one place.
+ */
+ if (chkdelta & 1) {
+ if (params->flags & IB_VERBOSE)
+ printf("target adjustment %04x was odd, correcting\n",
+ chkdelta);
+ assert(bb16[BB_ADJUST_OFFSET + 6] == 0);
+ assert(bb16[BB_ADJUST_OFFSET + 012] == 0);
+ bb16[BB_ADJUST_OFFSET + 6] += 0x8000;
+ bb16[BB_ADJUST_OFFSET + 012] += 0x8000;
+ }
+ resum(params, bb, bb16);
+ if (params->flags & IB_VERBOSE)
+ printf("final harmonized checksum: %016llx\n",
+ (unsigned long long)le64toh(bb->bb_cksum));
+ check_sparc(bb, "Final");
+}
+
+static void
+check_sparc(const struct alpha_boot_block * const bb, const char *when)
+{
+ uint16_t bb16[256];
+#define wmsg "%s sparc %s 0x%04x invalid, expected 0x%04x"
+
+ memcpy(bb16, bb, sizeof(bb16));
+ if (compute_sunsum(bb16) != bb16[255])
+ warnx(wmsg, when, "checksum", bb16[255], compute_sunsum(bb16));
+ if (bb16[254] != htobe16(SUN_DKMAGIC))
+ warnx(wmsg, when, "magic number", bb16[254],
+ htobe16(SUN_DKMAGIC));
+}
--- /dev/null
+/* $NetBSD: amiga.c,v 1.7 2010/01/14 16:27:49 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Michael Hitch.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: amiga.c,v 1.7 2010/01/14 16:27:49 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "installboot.h"
+
+/* XXX Must be kept in sync with bbstart.s! */
+#define CMDLN_LOC 0x10
+#define CMDLN_LEN 0x20
+
+#define CHKSUMOFFS 1
+
+u_int32_t chksum(u_int32_t *, int);
+
+static int amiga_setboot(ib_params *);
+
+struct ib_mach ib_mach_amiga =
+ { "amiga", amiga_setboot, no_clearboot, no_editboot,
+ IB_STAGE1START | IB_STAGE2START | IB_COMMAND };
+
+static int
+amiga_setboot(ib_params *params)
+{
+ int retval;
+ ssize_t rv;
+ char *dline;
+ int sumlen;
+ u_int32_t sum2, sum16;
+
+ struct stat bootstrapsb;
+
+ u_int32_t block[128*16];
+
+ retval = 0;
+ if (fstat(params->s1fd, &bootstrapsb) == -1) {
+ warn("Examining `%s'", params->stage1);
+ goto done;
+ }
+ if (!S_ISREG(bootstrapsb.st_mode)) {
+ warnx("`%s' must be a regular file", params->stage1);
+ goto done;
+ }
+
+ rv = pread(params->s1fd, &block, sizeof(block), 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ } else if (rv != sizeof(block)) {
+ warnx("Reading `%s': short read", params->stage1);
+ goto done;
+ }
+
+ /* XXX the choices should not be hardcoded */
+
+ sum2 = chksum(block, 1024/4);
+ sum16 = chksum(block, 8192/4);
+
+ if (sum16 == 0xffffffff) {
+ sumlen = 8192/4;
+ } else if (sum2 == 0xffffffff) {
+ sumlen = 1024/4;
+ } else {
+ errx(1, "%s: wrong checksum", params->stage1);
+ /* NOTREACHED */
+ }
+
+ if (sum2 == sum16) {
+ warnx("eek - both sums are the same");
+ }
+
+ if (params->flags & IB_COMMAND) {
+ dline = (char *)&(block[CMDLN_LOC/4]);
+ /* XXX keep the default default line in sync with bbstart.s */
+ if (strcmp(dline, "netbsd -ASn2") != 0) {
+ errx(1, "Old bootblock version? Can't change command line.");
+ }
+ (void)strncpy(dline, params->command, CMDLN_LEN-1);
+
+ block[1] = 0;
+ block[1] = 0xffffffff - chksum(block, sumlen);
+ }
+
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE)
+ printf("Writing boot block\n");
+ rv = pwrite(params->fsfd, &block, sizeof(block), 0);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(block)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else {
+ retval = 1;
+ }
+
+ done:
+ return (retval);
+}
+
+u_int32_t
+chksum(block, size)
+ u_int32_t *block;
+ int size;
+{
+ u_int32_t sum, lastsum;
+ int i;
+
+ sum = 0;
+
+ for (i=0; i<size; i++) {
+ lastsum = sum;
+ sum += htobe32(block[i]);
+ if (sum < lastsum)
+ ++sum;
+ }
+
+ return sum;
+}
--- /dev/null
+/* $NetBSD: emips.c,v 1.1 2011/01/26 01:18:55 pooka Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Simon Burge.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Ross Harvey. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ross Harvey
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: emips.c,v 1.1 2011/01/26 01:18:55 pooka Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/exec_elf.h>
+
+#include "installboot.h"
+
+static int emips_clearboot(ib_params *);
+static int emips_setboot(ib_params *);
+
+struct ib_mach ib_mach_emips =
+ { "emips", emips_setboot, emips_clearboot, no_editboot,
+ IB_STAGE1START | IB_APPEND | IB_SUNSUM };
+
+
+static int
+emips_clearboot(ib_params *params)
+{
+ /* Nothing to do */
+ return (1);
+}
+
+static int
+emips_setboot(ib_params *params)
+{
+ /* Nothing to do */
+ return (1);
+}
--- /dev/null
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: ews4800mips.c,v 1.2 2006/02/18 10:08:07 dsl Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+#include <unistd.h>
+#include <err.h>
+#include <stdio.h>
+#include "installboot.h"
+
+static int ews4800mips_setboot(ib_params *);
+
+struct ib_mach ib_mach_ews4800mips =
+ { "ews4800mips", ews4800mips_setboot, no_clearboot, no_editboot, 0};
+
+struct bbinfo_params ews4800mips_bbparams = {
+ EWS4800MIPS_BBINFO_MAGIC,
+ EWS4800MIPS_BOOT_BLOCK_OFFSET,
+ EWS4800MIPS_BOOT_BLOCK_BLOCKSIZE,
+ EWS4800MIPS_BOOT_BLOCK_MAX_SIZE,
+ 0,
+ BBINFO_BIG_ENDIAN,
+};
+
+static int
+ews4800mips_setboot(ib_params *params)
+{
+ u_int8_t buf[EWS4800MIPS_BOOT_BLOCK_MAX_SIZE];
+ int rv;
+
+ rv = pread(params->s1fd, buf, sizeof buf, 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ return 0;
+ } else if (rv != sizeof buf) {
+ warnx("Reading `%s' : short read", params->stage1);
+ return 0;
+ }
+
+ if (params->flags & IB_NOWRITE)
+ return 1;
+
+ if (params->flags & IB_VERBOSE)
+ printf("Writing boot block\n");
+
+ rv = pwrite(params->fsfd, buf, sizeof buf, 0);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ return 0;
+ } else if (rv != sizeof buf) {
+ warnx("Writing `%s': short write", params->filesystem);
+ return 0;
+ }
+
+ return 1;
+}
--- /dev/null
+/* $NetBSD: hp300.c,v 1.13 2011/02/10 23:25:11 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: hp300.c,v 1.13 2011/02/10 23:25:11 tsutsui Exp $");
+#endif /* !__lint */
+
+/* We need the target disklabel.h, not the hosts one..... */
+#ifdef HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#include <nbinclude/sys/disklabel.h>
+#else
+#include <sys/disklabel.h>
+#endif
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <md5.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static int hp300_setboot(ib_params *);
+
+struct ib_mach ib_mach_hp300 =
+ { "hp300", hp300_setboot, no_clearboot, no_editboot, IB_APPEND };
+
+static int
+hp300_setboot(ib_params *params)
+{
+ int retval;
+ uint8_t *bootstrap;
+ ssize_t rv;
+ struct partition *boot;
+ struct hp300_lifdir *lifdir;
+ int offset;
+ int i;
+ unsigned int secsize = HP300_SECTSIZE;
+ uint64_t boot_size, boot_offset;
+ struct disklabel *label;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ retval = 0;
+ bootstrap = MAP_FAILED;
+
+ label = malloc(params->sectorsize);
+ if (label == NULL) {
+ warn("Failed to allocate memory for disklabel");
+ goto done;
+ }
+
+ if (params->flags & IB_APPEND) {
+ if (!S_ISREG(params->fsstat.st_mode)) {
+ warnx(
+ "`%s' must be a regular file to append a bootstrap",
+ params->filesystem);
+ goto done;
+ }
+ boot_offset = roundup(params->fsstat.st_size, HP300_SECTSIZE);
+ } else {
+ /*
+ * The bootstrap can be well over 8k, and must go into a BOOT
+ * partition. Read NetBSD label to locate BOOT partition.
+ */
+ if (pread(params->fsfd, label, params->sectorsize,
+ LABELSECTOR * params->sectorsize)
+ != (ssize_t)params->sectorsize) {
+ warn("reading disklabel");
+ goto done;
+ }
+ /* And a quick validation - must be a big-endian label */
+ secsize = be32toh(label->d_secsize);
+ if (label->d_magic != htobe32(DISKMAGIC) ||
+ label->d_magic2 != htobe32(DISKMAGIC) ||
+ secsize == 0 || secsize & (secsize - 1) ||
+ be16toh(label->d_npartitions) > MAXMAXPARTITIONS) {
+ warnx("Invalid disklabel in %s", params->filesystem);
+ goto done;
+ }
+
+ i = be16toh(label->d_npartitions);
+ for (boot = label->d_partitions; ; boot++) {
+ if (--i < 0) {
+ warnx("No BOOT partition");
+ goto done;
+ }
+ if (boot->p_fstype == FS_BOOT)
+ break;
+ }
+ boot_size = be32toh(boot->p_size) * (uint64_t)secsize;
+ boot_offset = be32toh(boot->p_offset) * (uint64_t)secsize;
+
+ /*
+ * We put the entire LIF file into the BOOT partition even when
+ * it doesn't start at the beginning of the disk.
+ *
+ * Maybe we ought to be able to take a binary file and add
+ * it to the LIF filesystem.
+ */
+ if (boot_size < (uint64_t)params->s1stat.st_size) {
+ warn("BOOT partition too small (%llu < %llu)",
+ (unsigned long long)boot_size,
+ (unsigned long long)params->s1stat.st_size);
+ goto done;
+ }
+ }
+
+ bootstrap = mmap(NULL, params->s1stat.st_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, params->s1fd, 0);
+ if (bootstrap == MAP_FAILED) {
+ warn("mmaping `%s'", params->stage1);
+ goto done;
+ }
+
+ /* Relocate files, sanity check LIF directory on the way */
+ lifdir = (void *)(bootstrap + HP300_SECTSIZE * 2);
+ for (i = 0; i < 8; lifdir++, i++) {
+ int32_t addr = be32toh(lifdir->dir_addr);
+ int32_t limit = (params->s1stat.st_size - 1) / HP300_SECTSIZE + 1;
+ int32_t end = addr + be32toh(lifdir->dir_length);
+ if (end > limit) {
+ warnx("LIF entry %d larger (%d %d) than LIF file",
+ i, end, limit);
+ goto done;
+ }
+ if (addr != 0 && boot_offset != 0)
+ lifdir->dir_addr = htobe32(addr + boot_offset
+ / HP300_SECTSIZE);
+ }
+
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ /* Write LIF volume header and directory to sectors 0 and 1 */
+ rv = pwrite(params->fsfd, bootstrap, 1024, 0);
+ if (rv != 1024) {
+ if (rv == -1)
+ warn("Writing `%s'", params->filesystem);
+ else
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+
+ /* Write files to BOOT partition */
+ offset = boot_offset <= HP300_SECTSIZE * 16 ? HP300_SECTSIZE * 16 : 0;
+ i = roundup(params->s1stat.st_size, secsize) - offset;
+ rv = pwrite(params->fsfd, bootstrap + offset, i, boot_offset + offset);
+ if (rv != i) {
+ if (rv == -1)
+ warn("Writing boot filesystem of `%s'",
+ params->filesystem);
+ else
+ warnx("Writing boot filesystem of `%s': short write",
+ params->filesystem);
+ goto done;
+ }
+
+ retval = 1;
+
+ done:
+ if (label != NULL)
+ free(label);
+ if (bootstrap != MAP_FAILED)
+ munmap(bootstrap, params->s1stat.st_size);
+ return retval;
+}
--- /dev/null
+/* $NetBSD: hp700.c,v 1.4 2008/04/28 20:24:16 martin Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: hp700.c,v 1.4 2008/04/28 20:24:16 martin Exp $");
+#endif /* !__lint */
+
+/* We need the target disklabel.h, not the hosts one..... */
+#ifdef HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#include <nbinclude/sys/disklabel.h>
+#else
+#include <sys/disklabel.h>
+#endif
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+#define HP700_LABELOFFSET 512
+#define HP700_LABELSIZE 404 /* reserve 16 partitions */
+#define HP700_BOOT_BLOCK_SIZE 8192
+
+static int hp700_clearboot(ib_params *);
+static int hp700_setboot(ib_params *);
+
+struct ib_mach ib_mach_hp700 =
+ { "hp700", hp700_setboot, hp700_clearboot, no_editboot, 0};
+
+static int
+hp700_clearboot(ib_params *params)
+{
+ char bb[HP700_BOOT_BLOCK_SIZE];
+ int retval, eol;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+
+ retval = 0;
+
+ /* read disklabel on the target disk */
+ rv = pread(params->fsfd, bb, sizeof bb, 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof bb) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ /* clear header */
+ memset(bb, 0, HP700_LABELOFFSET);
+ eol = HP700_LABELOFFSET + HP700_LABELSIZE;
+ memset(&bb[eol], 0, sizeof bb - eol);
+
+ if (params->flags & IB_VERBOSE) {
+ printf("%slearing bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not c" : "C");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ rv = pwrite(params->fsfd, bb, sizeof bb, 0);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != HP700_BOOT_BLOCK_SIZE) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else
+ retval = 1;
+
+ done:
+ return (retval);
+}
+
+static int
+hp700_setboot(ib_params *params)
+{
+ struct stat bootstrapsb;
+ char bb[HP700_BOOT_BLOCK_SIZE];
+ struct {
+ char l_off[HP700_LABELOFFSET];
+ struct disklabel l;
+ char l_pad[HP700_BOOT_BLOCK_SIZE
+ - HP700_LABELOFFSET - sizeof(struct disklabel)];
+ } label;
+ unsigned int secsize, npart;
+ int retval;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ retval = 0;
+
+ /* read disklabel on the target disk */
+ rv = pread(params->fsfd, &label, HP700_BOOT_BLOCK_SIZE, 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != HP700_BOOT_BLOCK_SIZE) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ if (fstat(params->s1fd, &bootstrapsb) == -1) {
+ warn("Examining `%s'", params->stage1);
+ goto done;
+ }
+ if (!S_ISREG(bootstrapsb.st_mode)) {
+ warnx("`%s' must be a regular file", params->stage1);
+ goto done;
+ }
+
+ /* check if valid disklabel exists */
+ secsize = be32toh(label.l.d_secsize);
+ npart = be16toh(label.l.d_npartitions);
+ if (label.l.d_magic != htobe32(DISKMAGIC) ||
+ label.l.d_magic2 != htobe32(DISKMAGIC) ||
+ secsize == 0 || secsize & (secsize - 1) ||
+ npart > MAXMAXPARTITIONS) {
+ warnx("No disklabel in `%s'", params->filesystem);
+
+ /* then check if boot partition exists */
+ } else if (npart < 1 || label.l.d_partitions[0].p_size == 0) {
+ warnx("Partition `a' doesn't exist in %s", params->filesystem);
+
+ /* check if the boot partition is below 2GB */
+ } else if (be32toh(label.l.d_partitions[0].p_offset) +
+ be32toh(label.l.d_partitions[0].p_size) >
+ ((unsigned)2*1024*1024*1024) / secsize) {
+ warnx("WARNING: Partition `a' of `%s' exceeds 2GB boundary.",
+ params->filesystem);
+ warnx("WARNING: It won't boot since hp700 PDC can handle only 2GB.");
+ }
+
+ /* read boot loader */
+ memset(&bb, 0, sizeof bb);
+ rv = read(params->s1fd, &bb, sizeof bb);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ }
+ /* then, overwrite disklabel */
+ memcpy(&bb[HP700_LABELOFFSET], &label.l, HP700_LABELSIZE);
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %#x\n", 0);
+ printf("Bootstrap byte count: %#zx\n", rv);
+ printf("%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ /* write boot loader and disklabel into the target disk */
+ rv = pwrite(params->fsfd, &bb, HP700_BOOT_BLOCK_SIZE, 0);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != HP700_BOOT_BLOCK_SIZE) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else
+ retval = 1;
+
+ done:
+ return (retval);
+}
--- /dev/null
+/* $NetBSD: i386.c,v 1.37 2011/08/14 17:50:17 christos Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: i386.c,v 1.37 2011/08/14 17:50:17 christos Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+#ifndef HAVE_NBTOOL_CONFIG_H
+#include <sys/ioctl.h>
+#include <sys/dkio.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <err.h>
+#include <md5.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static const struct console_name {
+ const char *name; /* Name of console selection */
+ const int dev; /* value matching CONSDEV_* from sys/arch/i386/stand/lib/libi386.h */
+} consoles[] = {
+ { "pc", 0 /* CONSDEV_PC */ },
+ { "com0", 1 /* CONSDEV_COM0 */ },
+ { "com1", 2 /* CONSDEV_COM1 */ },
+ { "com2", 3 /* CONSDEV_COM2 */ },
+ { "com3", 4 /* CONSDEV_COM3 */ },
+ { "com0kbd", 5 /* CONSDEV_COM0KBD */ },
+ { "com1kbd", 6 /* CONSDEV_COM1KBD */ },
+ { "com2kbd", 7 /* CONSDEV_COM2KBD */ },
+ { "com3kbd", 8 /* CONSDEV_COM3KBD */ },
+ { "auto", -1 /* CONSDEV_AUTO */ },
+};
+
+static int i386_setboot(ib_params *);
+static int i386_editboot(ib_params *);
+
+struct ib_mach ib_mach_i386 =
+ { "i386", i386_setboot, no_clearboot, i386_editboot,
+ IB_RESETVIDEO | IB_CONSOLE | IB_CONSPEED | IB_CONSADDR |
+ IB_KEYMAP | IB_PASSWORD | IB_TIMEOUT |
+ IB_MODULES | IB_BOOTCONF };
+
+struct ib_mach ib_mach_amd64 =
+ { "amd64", i386_setboot, no_clearboot, i386_editboot,
+ IB_RESETVIDEO | IB_CONSOLE | IB_CONSPEED | IB_CONSADDR |
+ IB_KEYMAP | IB_PASSWORD | IB_TIMEOUT |
+ IB_MODULES | IB_BOOTCONF };
+
+/*
+ * Attempting to write the 'labelsector' (or a sector near it - within 8k?)
+ * using the non-raw disk device fails silently. This can be detected (today)
+ * by doing a fsync() and a read back.
+ * This is very likely to affect installboot, indeed the code may need to
+ * be written into the 'labelsector' itself - especially on non-512 byte media.
+ * We do all writes with a read verify.
+ * If EROFS is returned we also try to enable writes to the label sector.
+ * (Maybe these functions should be in the generic part of installboot.)
+ */
+static int
+pwrite_validate(int fd, const void *buf, size_t n_bytes, off_t offset)
+{
+ void *r_buf;
+ ssize_t rv;
+
+ r_buf = malloc(n_bytes);
+ if (r_buf == NULL)
+ return -1;
+ rv = pwrite(fd, buf, n_bytes, offset);
+ if (rv == -1) {
+ free(r_buf);
+ return -1;
+ }
+ fsync(fd);
+ if (pread(fd, r_buf, rv, offset) == rv && memcmp(r_buf, buf, rv) == 0) {
+ free(r_buf);
+ return rv;
+ }
+ free(r_buf);
+ errno = EROFS;
+ return -1;
+}
+
+static int
+write_boot_area(ib_params *params, uint8_t *buf, size_t len)
+{
+ int rv, i;
+
+ /*
+ * Writing the 'label' sector (likely to be bytes 512-1023) could
+ * fail, so we try to avoid writing that area.
+ * Unfortunately, if we are accessing the raw disk, and the sector
+ * size is larger than 512 bytes that is also doomed.
+ * See how we get on....
+ *
+ * NB: Even if the physical sector size is not 512, the space for
+ * the label is 512 bytes from the start of the disk.
+ * So all the '512' constants in these functions are correct.
+ */
+
+ /* Write out first 512 bytes - the pbr code */
+ rv = pwrite_validate(params->fsfd, buf, 512, 0);
+ if (rv == 512) {
+ /* That worked, do the rest */
+ if (len == 512)
+ return 1;
+ len -= 512 * 2;
+ rv = pwrite_validate(params->fsfd, buf + 512 * 2, len, 512 * 2);
+ if (rv != (ssize_t)len)
+ goto bad_write;
+ return 1;
+ }
+ if (rv != -1 || (errno != EINVAL && errno != EROFS))
+ goto bad_write;
+
+ if (errno == EINVAL) {
+ /* Assume the failure was due to to the sector size > 512 */
+ rv = pwrite_validate(params->fsfd, buf, len, 0);
+ if (rv == (ssize_t)len)
+ return 1;
+ if (rv != -1 || (errno != EROFS))
+ goto bad_write;
+ }
+
+#ifdef DIOCWLABEL
+ /* Pesky label is protected, try to unprotect it */
+ i = 1;
+ rv = ioctl(params->fsfd, DIOCWLABEL, &i);
+ if (rv != 0) {
+ warn("Cannot enable writes to the label sector");
+ return 0;
+ }
+ /* Try again with label write-enabled */
+ rv = pwrite_validate(params->fsfd, buf, len, 0);
+
+ /* Reset write-protext */
+ i = 0;
+ ioctl(params->fsfd, DIOCWLABEL, &i);
+ if (rv == (ssize_t)len)
+ return 1;
+#endif
+
+ bad_write:
+ if (rv == -1)
+ warn("Writing `%s'", params->filesystem);
+ else
+ warnx("Writing `%s': short write, %u bytes",
+ params->filesystem, rv);
+ return 0;
+}
+
+static void
+show_i386_boot_params(struct x86_boot_params *bpp)
+{
+ size_t i;
+
+ printf("Boot options: ");
+ printf("timeout %d, ", le32toh(bpp->bp_timeout));
+ printf("flags %x, ", le32toh(bpp->bp_flags));
+ printf("speed %d, ", le32toh(bpp->bp_conspeed));
+ printf("ioaddr %x, ", le32toh(bpp->bp_consaddr));
+ for (i = 0; i < __arraycount(consoles); i++) {
+ if (consoles[i].dev == (int)le32toh(bpp->bp_consdev))
+ break;
+ }
+ if (i == __arraycount(consoles))
+ printf("console %d\n", le32toh(bpp->bp_consdev));
+ else
+ printf("console %s\n", consoles[i].name);
+ if (bpp->bp_keymap[0])
+ printf(" keymap %s\n", bpp->bp_keymap);
+}
+
+static int
+is_zero(const uint8_t *p, unsigned int len)
+{
+ return len == 0 || (p[0] == 0 && memcmp(p, p + 1, len - 1) == 0);
+}
+
+static int
+update_i386_boot_params(ib_params *params, struct x86_boot_params *bpp)
+{
+ struct x86_boot_params bp;
+ uint32_t bplen;
+ size_t i;
+
+ bplen = le32toh(bpp->bp_length);
+ if (bplen > sizeof bp)
+ /* Ignore pad space in bootxx */
+ bplen = sizeof bp;
+
+ /* Take (and update) local copy so we handle size mismatches */
+ memset(&bp, 0, sizeof bp);
+ memcpy(&bp, bpp, bplen);
+
+ if (params->flags & IB_TIMEOUT)
+ bp.bp_timeout = htole32(params->timeout);
+ if (params->flags & IB_RESETVIDEO)
+ bp.bp_flags ^= htole32(X86_BP_FLAGS_RESET_VIDEO);
+ if (params->flags & IB_CONSPEED)
+ bp.bp_conspeed = htole32(params->conspeed);
+ if (params->flags & IB_CONSADDR)
+ bp.bp_consaddr = htole32(params->consaddr);
+ if (params->flags & IB_CONSOLE) {
+ for (i = 0; i < __arraycount(consoles); i++)
+ if (strcmp(consoles[i].name, params->console) == 0)
+ break;
+
+ if (i == __arraycount(consoles)) {
+ warnx("invalid console name, valid names are:");
+ (void)fprintf(stderr, "\t%s", consoles[0].name);
+ for (i = 1; consoles[i].name != NULL; i++)
+ (void)fprintf(stderr, ", %s", consoles[i].name);
+ (void)fprintf(stderr, "\n");
+ return 1;
+ }
+ bp.bp_consdev = htole32(consoles[i].dev);
+ }
+ if (params->flags & IB_PASSWORD) {
+ if (params->password[0]) {
+ MD5_CTX md5ctx;
+ MD5Init(&md5ctx);
+ MD5Update(&md5ctx, params->password,
+ strlen(params->password));
+ MD5Final(bp.bp_password, &md5ctx);
+ bp.bp_flags |= htole32(X86_BP_FLAGS_PASSWORD);
+ } else {
+ memset(&bp.bp_password, 0, sizeof bp.bp_password);
+ bp.bp_flags &= ~htole32(X86_BP_FLAGS_PASSWORD);
+ }
+ }
+ if (params->flags & IB_KEYMAP)
+ strlcpy(bp.bp_keymap, params->keymap, sizeof bp.bp_keymap);
+ if (params->flags & IB_MODULES)
+ bp.bp_flags ^= htole32(X86_BP_FLAGS_NOMODULES);
+ if (params->flags & IB_BOOTCONF)
+ bp.bp_flags ^= htole32(X86_BP_FLAGS_NOBOOTCONF);
+
+ if (params->flags & (IB_NOWRITE | IB_VERBOSE))
+ show_i386_boot_params(&bp);
+
+ /* Check we aren't trying to set anything we can't save */
+ if (!is_zero((char *)&bp + bplen, sizeof bp - bplen)) {
+ warnx("Patch area in stage1 bootstrap is too small");
+ return 1;
+ }
+ memcpy(bpp, &bp, bplen);
+ return 0;
+}
+
+static int
+i386_setboot(ib_params *params)
+{
+ unsigned int u;
+ ssize_t rv;
+ uint32_t *magic, expected_magic;
+ union {
+ struct mbr_sector mbr;
+ uint8_t b[8192];
+ } disk_buf, bootstrap;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ /*
+ * There is only 8k of space in a FFSv1 partition (and ustarfs)
+ * so ensure we don't splat over anything important.
+ */
+ if (params->s1stat.st_size > (off_t)(sizeof bootstrap)) {
+ warnx("stage1 bootstrap `%s' (%u bytes) is larger than 8192 bytes",
+ params->stage1, (unsigned int)params->s1stat.st_size);
+ return 0;
+ }
+ if (params->s1stat.st_size < 3 * 512 && params->s1stat.st_size != 512) {
+ warnx("stage1 bootstrap `%s' (%u bytes) is too small",
+ params->stage1, (unsigned int)params->s1stat.st_size);
+ return 0;
+ }
+
+ /* Read in the existing disk header and boot code */
+ rv = pread(params->fsfd, &disk_buf, sizeof (disk_buf), 0);
+ if (rv != sizeof(disk_buf)) {
+ if (rv == -1)
+ warn("Reading `%s'", params->filesystem);
+ else
+ warnx("Reading `%s': short read, %ld bytes"
+ " (should be %ld)", params->filesystem, (long)rv,
+ (long)sizeof(disk_buf));
+ return 0;
+ }
+
+ if (disk_buf.mbr.mbr_magic != le16toh(MBR_MAGIC)) {
+ if (params->flags & IB_VERBOSE) {
+ printf(
+ "Ignoring PBR with invalid magic in sector 0 of `%s'\n",
+ params->filesystem);
+ }
+ memset(&disk_buf, 0, 512);
+ }
+
+ /* Read the new bootstrap code. */
+ rv = pread(params->s1fd, &bootstrap, params->s1stat.st_size, 0);
+ if (rv != params->s1stat.st_size) {
+ if (rv == -1)
+ warn("Reading `%s'", params->stage1);
+ else
+ warnx("Reading `%s': short read, %ld bytes"
+ " (should be %ld)", params->stage1, (long)rv,
+ (long)params->s1stat.st_size);
+ return 0;
+ }
+
+ /*
+ * The bootstrap code is either 512 bytes for booting FAT16, or best
+ * part of 8k (with bytes 512-1023 all zeros).
+ */
+ if (params->s1stat.st_size == 512) {
+ /* Magic number is at end of pbr code */
+ magic = (void *)(bootstrap.b + 512 - 16 + 4);
+ expected_magic = htole32(X86_BOOT_MAGIC_FAT);
+ } else {
+ /* Magic number is at start of sector following label */
+ magic = (void *)(bootstrap.b + 512 * 2 + 4);
+ expected_magic = htole32(X86_BOOT_MAGIC_1);
+ /*
+ * For a variety of reasons we restrict our 'normal' partition
+ * boot code to a size which enable it to be used as mbr code.
+ * IMHO this is bugus (dsl).
+ */
+ if (!is_zero(bootstrap.b + 512-2-64, 64)) {
+ warnx("Data in mbr partition table of new bootstrap");
+ return 0;
+ }
+ if (!is_zero(bootstrap.b + 512, 512)) {
+ warnx("Data in label part of new bootstrap");
+ return 0;
+ }
+ /* Copy mbr table and label from existing disk buffer */
+ memcpy(bootstrap.b + 512-2-64, disk_buf.b + 512-2-64, 64);
+ memcpy(bootstrap.b + 512, disk_buf.b + 512, 512);
+ }
+
+ /* Validate the 'magic number' that marks the parameter block */
+ if (*magic != expected_magic) {
+ warnx("Invalid magic in stage1 bootstrap %x != %x",
+ *magic, expected_magic);
+ return 0;
+ }
+
+ /*
+ * If the partition has a FAT (or NTFS) filesystem, then we must
+ * preserve the BIOS Parameter Block (BPB).
+ * It is also very likely that there isn't 8k of space available
+ * for (say) bootxx_msdos, and that blindly installing it will trash
+ * the FAT filesystem.
+ * To avoid this we check the number of 'reserved' sectors to ensure
+ * there there is enough space.
+ * Unfortunately newfs(8) doesn't (yet) splat the BPB (which is
+ * effectively the FAT superblock) when a filesystem is initailised
+ * so this code tends to complain rather too often,
+ * Specifying 'installboot -f' will delete the old BPB info.
+ */
+ if (!(params->flags & IB_FORCE)) {
+ #define USE_F ", use -f (may invalidate filesystem)"
+ /*
+ * For FAT compatibility, the pbr code starts 'jmp xx; nop'
+ * followed by the BIOS Parameter Block (BPB).
+ * The 2nd byte (jump offset) is the size of the nop + BPB.
+ */
+ if (bootstrap.b[0] != 0xeb || bootstrap.b[2] != 0x90) {
+ warnx("No BPB in new bootstrap %02x:%02x:%02x" USE_F,
+ bootstrap.b[0], bootstrap.b[1], bootstrap.b[2]);
+ return 0;
+ }
+
+ /* Find size of old BPB, and copy into new bootcode */
+ if (!is_zero(disk_buf.b + 3 + 8, disk_buf.b[1] - 1 - 8)) {
+ struct mbr_bpbFAT16 *bpb = (void *)(disk_buf.b + 3 + 8);
+ /* Check enough space before the FAT for the bootcode */
+ u = le16toh(bpb->bpbBytesPerSec)
+ * le16toh(bpb->bpbResSectors);
+ if (u != 0 && u < params->s1stat.st_size) {
+ warnx("Insufficient reserved space before FAT "
+ "(%u bytes available)" USE_F, u);
+ return 0;
+ }
+ /* Check we have enough space for the old bpb */
+ if (disk_buf.b[1] > bootstrap.b[1]) {
+ /* old BPB is larger, allow if extra zeros */
+ if (!is_zero(disk_buf.b + 2 + bootstrap.b[1],
+ disk_buf.b[1] - bootstrap.b[1])) {
+ warnx("Old BPB too big" USE_F);
+ return 0;
+ }
+ u = bootstrap.b[1];
+ } else {
+ /* Old BPB is shorter, leave zero filled */
+ u = disk_buf.b[1];
+ }
+ memcpy(bootstrap.b + 2, disk_buf.b + 2, u);
+ }
+ #undef USE_F
+ }
+
+ /*
+ * Fill in any user-specified options into the
+ * struct x86_boot_params
+ * that follows the magic number.
+ * See sys/arch/i386/stand/bootxx/bootxx.S for more information.
+ */
+ if (update_i386_boot_params(params, (void *)(magic + 1)))
+ return 0;
+
+ if (params->flags & IB_NOWRITE) {
+ return 1;
+ }
+
+ /* Copy new bootstrap data into disk buffer, ignoring label area */
+ memcpy(&disk_buf, &bootstrap, 512);
+ if (params->s1stat.st_size > 512 * 2) {
+ memcpy(disk_buf.b + 2 * 512, bootstrap.b + 2 * 512,
+ params->s1stat.st_size - 2 * 512);
+ /* Zero pad to 512 byte sector boundary */
+ memset(disk_buf.b + params->s1stat.st_size, 0,
+ (8192 - params->s1stat.st_size) & 511);
+ }
+
+ return write_boot_area(params, disk_buf.b, sizeof disk_buf.b);
+}
+
+static int
+i386_editboot(ib_params *params)
+{
+ int retval;
+ uint8_t buf[512];
+ ssize_t rv;
+ uint32_t magic;
+ uint32_t offset;
+ struct x86_boot_params *bpp;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+
+ retval = 0;
+
+ /*
+ * Read in the existing bootstrap.
+ * Look in any of the first 4 sectors.
+ */
+
+ bpp = NULL;
+ for (offset = 0; offset < 4 * 512; offset += 512) {
+ rv = pread(params->fsfd, &buf, sizeof buf, offset);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof buf) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ /* Magic number is 4 bytes in (to allow for a jmps) */
+ /* Also allow any of the magic numbers. */
+ magic = le32toh(*(uint32_t *)(buf + 4)) | 0xf;
+ if (magic != (X86_BOOT_MAGIC_1 | 0xf))
+ continue;
+
+ /* The parameters are just after the magic number */
+ bpp = (void *)(buf + 8);
+ break;
+ }
+ if (bpp == NULL) {
+ warnx("Invalid magic in existing bootstrap");
+ goto done;
+ }
+
+ /*
+ * Fill in any user-specified options into the
+ * struct x86_boot_params
+ * that's 8 bytes in from the start of the third sector.
+ * See sys/arch/i386/stand/bootxx/bootxx.S for more information.
+ */
+ if (update_i386_boot_params(params, bpp))
+ goto done;
+
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ /*
+ * Write boot code back
+ */
+ rv = pwrite(params->fsfd, buf, sizeof buf, offset);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof buf) {
+ warnx("Writing `%s': short write, %zd bytes (should be %zu)",
+ params->filesystem, rv, sizeof(buf));
+ goto done;
+ }
+
+ retval = 1;
+
+ done:
+ return retval;
+}
--- /dev/null
+/* $NetBSD: landisk.c,v 1.5 2009/05/07 07:03:39 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: landisk.c,v 1.5 2009/05/07 07:03:39 lukem Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <md5.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static int landisk_setboot(ib_params *);
+
+struct ib_mach ib_mach_landisk =
+ { "landisk", landisk_setboot, no_clearboot, no_editboot,
+ IB_TIMEOUT };
+
+static int
+landisk_setboot(ib_params *params)
+{
+ struct mbr_sector mbr;
+ struct landisk_boot_params bp, *bpp;
+ uint8_t *bootstrapbuf;
+ ssize_t rv;
+ uint32_t magic;
+ size_t bootstrapsize;
+ int retval, i;
+ uint32_t bplen;
+ int bpbsize;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ retval = 0;
+ bootstrapbuf = NULL;
+
+ /*
+ * There is only 8k of space in a FFSv1 partition (and ustarfs)
+ * so ensure we don't splat over anything important.
+ */
+ if (params->s1stat.st_size > 8192) {
+ warnx("stage1 bootstrap `%s' is larger than 8192 bytes",
+ params->stage1);
+ goto done;
+ }
+
+ /*
+ * Read in the existing MBR.
+ */
+ rv = pread(params->fsfd, &mbr, sizeof(mbr), MBR_BBSECTOR);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(mbr)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+ if (mbr.mbr_magic != le16toh(MBR_MAGIC)) {
+ if (params->flags & IB_VERBOSE) {
+ printf(
+ "Ignoring MBR with invalid magic in sector 0 of `%s'\n",
+ params->filesystem);
+ }
+ memset(&mbr, 0, sizeof(mbr));
+ }
+
+ /*
+ * Allocate a buffer, with space to round up the input file
+ * to the next block size boundary, and with space for the boot
+ * block.
+ */
+ bootstrapsize = roundup(params->s1stat.st_size, 512);
+
+ bootstrapbuf = malloc(bootstrapsize);
+ if (bootstrapbuf == NULL) {
+ warn("Allocating %zu bytes", bootstrapsize);
+ goto done;
+ }
+ memset(bootstrapbuf, 0, bootstrapsize);
+
+ /*
+ * Read the file into the buffer.
+ */
+ rv = pread(params->s1fd, bootstrapbuf, params->s1stat.st_size, 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ } else if (rv != params->s1stat.st_size) {
+ warnx("Reading `%s': short read", params->stage1);
+ goto done;
+ }
+
+ magic = *(uint32_t *)(bootstrapbuf + 512 * 2 + 4);
+ if (magic != htole32(LANDISK_BOOT_MAGIC_1)) {
+ warnx("Invalid magic in stage1 boostrap %x != %x",
+ magic, htole32(LANDISK_BOOT_MAGIC_1));
+ goto done;
+ }
+
+ /*
+ * Determine size of BIOS Parameter Block (BPB) to copy from
+ * original MBR to the temporary buffer by examining the first
+ * few instruction in the new bootblock. Supported values:
+ * 2b a0 11 jmp ENDOF(mbr_bpbFAT32)+1, nop
+ * (anything else) ; don't preserve
+ */
+ bpbsize = 0;
+#if 0
+ if (bootstrapbuf[1] == 0xa0 && bootstrapbuf[2] == 0x11 &&
+ (bootstrapbuf[0] == 0x2b /*|| bootstrapbuf[0] == 0x1d*/)) {
+ bpbsize = bootstrapbuf[0] + 2 - MBR_BPB_OFFSET;
+ }
+#endif
+
+ /*
+ * Ensure bootxx hasn't got any code or data (i.e, non-zero bytes) in
+ * the partition table.
+ */
+ for (i = 0; i < (int)sizeof(mbr.mbr_parts); i++) {
+ if (*(uint8_t *)(bootstrapbuf + MBR_PART_OFFSET + i) != 0) {
+ warnx(
+ "Partition table has non-zero byte at offset %d in `%s'",
+ MBR_PART_OFFSET + i, params->stage1);
+ goto done;
+ }
+ }
+
+#if 0
+ /*
+ * Copy the BPB and the partition table from the original MBR to the
+ * temporary buffer so that they're written back to the fs.
+ */
+ if (bpbsize != 0) {
+ if (params->flags & IB_VERBOSE)
+ printf("Preserving %d (%#x) bytes of the BPB\n",
+ bpbsize, bpbsize);
+ (void)memcpy(bootstrapbuf + MBR_BPB_OFFSET, &mbr.mbr_bpb,
+ bpbsize);
+ }
+#endif
+ memcpy(bootstrapbuf + MBR_PART_OFFSET, &mbr.mbr_parts,
+ sizeof(mbr.mbr_parts));
+
+ /*
+ * Fill in any user-specified options into the
+ * struct landisk_boot_params
+ * that's 8 bytes in from the start of the third sector.
+ * See sys/arch/landisk/stand/bootxx/bootxx.S for more information.
+ */
+ bpp = (void *)(bootstrapbuf + 512 * 2 + 8);
+ bplen = le32toh(bpp->bp_length);
+ if (bplen > sizeof bp)
+ /* Ignore pad space in bootxx */
+ bplen = sizeof bp;
+ /* Take (and update) local copy so we handle size mismatches */
+ memset(&bp, 0, sizeof bp);
+ memcpy(&bp, bpp, bplen);
+ if (params->flags & IB_TIMEOUT)
+ bp.bp_timeout = htole32(params->timeout);
+ /* Check we aren't trying to set anything we can't save */
+ if (bplen < sizeof bp && memcmp((char *)&bp + bplen,
+ (char *)&bp + bplen + 1,
+ sizeof bp - bplen - 1) != 0) {
+ warnx("Patch area in stage1 bootstrap is too small");
+ goto done;
+ }
+ memcpy(bpp, &bp, bplen);
+
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ /*
+ * Write MBR code to sector zero.
+ */
+ rv = pwrite(params->fsfd, bootstrapbuf, 512, 0);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != 512) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+
+ /*
+ * Skip disklabel in sector 1 and write bootxx to sectors 2..N.
+ */
+ rv = pwrite(params->fsfd, bootstrapbuf + 512 * 2,
+ bootstrapsize - 512 * 2, 512 * 2);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if ((size_t)rv != bootstrapsize - 512 * 2) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+
+ retval = 1;
+
+ done:
+ if (bootstrapbuf)
+ free(bootstrapbuf);
+ return retval;
+}
--- /dev/null
+/* $NetBSD: macppc.c,v 1.11 2008/05/24 19:15:21 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: macppc.c,v 1.11 2008/05/24 19:15:21 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+#ifndef HAVE_NBTOOL_CONFIG_H
+#include <sys/ioctl.h>
+#include <sys/dkio.h>
+#include <errno.h>
+#endif
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static struct bbinfo_params bbparams = {
+ MACPPC_BBINFO_MAGIC,
+ MACPPC_BOOT_BLOCK_OFFSET,
+ MACPPC_BOOT_BLOCK_BLOCKSIZE,
+ MACPPC_BOOT_BLOCK_MAX_SIZE,
+ 0,
+ BBINFO_BIG_ENDIAN,
+};
+
+static int writeapplepartmap(ib_params *, struct bbinfo_params *, uint8_t *);
+
+static int macppc_clearboot(ib_params *);
+static int macppc_setboot(ib_params *);
+
+struct ib_mach ib_mach_macppc =
+ { "macppc", macppc_setboot, macppc_clearboot, no_editboot,
+ IB_STAGE2START };
+
+static int
+macppc_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ /* XXX: maybe clear the apple partition map too? */
+ return (shared_bbinfo_clearboot(params, &bbparams, NULL));
+}
+
+static int
+macppc_setboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_setboot(params, &bbparams, writeapplepartmap));
+}
+
+
+static int
+writeapplepartmap(ib_params *params, struct bbinfo_params *bb_params,
+ uint8_t *bb)
+{
+ struct apple_drvr_map dm;
+ struct apple_part_map_entry pme;
+ int rv;
+
+ assert (params != NULL);
+ assert (bb_params != NULL);
+ assert (bb != NULL);
+
+ if (params->flags & IB_NOWRITE)
+ return (1);
+
+ /* block 0: driver map */
+ if (pread(params->fsfd, &dm, MACPPC_BOOT_BLOCK_BLOCKSIZE, 0) !=
+ MACPPC_BOOT_BLOCK_BLOCKSIZE) {
+ warn("Can't read sector 0 of `%s'", params->filesystem);
+ return (0);
+ }
+ dm.sbSig = htobe16(APPLE_DRVR_MAP_MAGIC);
+ dm.sbBlockSize = htobe16(512);
+ dm.sbBlkCount = htobe32(0);
+
+ rv = pwrite(params->fsfd, &dm, MACPPC_BOOT_BLOCK_BLOCKSIZE, 0);
+#ifdef DIOCWLABEL
+ if (rv == -1 && errno == EROFS) {
+ /*
+ * block 0 is LABELSECTOR which might be protected by
+ * bounds_check_with_label(9).
+ */
+ int enable;
+
+ enable = 1;
+ rv = ioctl(params->fsfd, DIOCWLABEL, &enable);
+ if (rv != 0) {
+ warn("Cannot enable writes to the label sector");
+ return 0;
+ }
+
+ rv = pwrite(params->fsfd, &dm, MACPPC_BOOT_BLOCK_BLOCKSIZE, 0);
+
+ /* Reset write-protect. */
+ enable = 0;
+ (void)ioctl(params->fsfd, DIOCWLABEL, &enable);
+ }
+#endif
+ if (rv != MACPPC_BOOT_BLOCK_BLOCKSIZE) {
+ warn("Can't write sector 0 of `%s'", params->filesystem);
+ return (0);
+ }
+
+ /* block 1: Apple Partition Map */
+ memset(&pme, 0, sizeof(pme));
+ pme.pmSig = htobe16(APPLE_PART_MAP_ENTRY_MAGIC);
+ pme.pmMapBlkCnt = htobe32(2);
+ pme.pmPyPartStart = htobe32(1);
+ pme.pmPartBlkCnt = htobe32(2);
+ pme.pmDataCnt = htobe32(2);
+ strlcpy(pme.pmPartName, "Apple", sizeof(pme.pmPartName));
+ strlcpy(pme.pmPartType, "Apple_partition_map", sizeof(pme.pmPartType));
+ pme.pmPartStatus = htobe32(0x37);
+ if (pwrite(params->fsfd, &pme, MACPPC_BOOT_BLOCK_BLOCKSIZE,
+ 1 * MACPPC_BOOT_BLOCK_BLOCKSIZE) != MACPPC_BOOT_BLOCK_BLOCKSIZE) {
+ warn("Can't write Apple Partition Map into sector 1 of `%s'",
+ params->filesystem);
+ return (0);
+ }
+
+ /* block 2: NetBSD partition */
+ memset(&pme, 0, sizeof(pme));
+ pme.pmSig = htobe16(APPLE_PART_MAP_ENTRY_MAGIC);
+ pme.pmMapBlkCnt = htobe32(2);
+ pme.pmPyPartStart = htobe32(4);
+ pme.pmPartBlkCnt = htobe32(0x7fffffff);
+ pme.pmDataCnt = htobe32(0x7fffffff);
+ strlcpy(pme.pmPartName, "NetBSD", sizeof(pme.pmPartName));
+ strlcpy(pme.pmPartType, "NetBSD/macppc", sizeof(pme.pmPartType));
+ pme.pmPartStatus = htobe32(0x3b);
+ pme.pmBootSize = htobe32(roundup(params->s1stat.st_size, 512));
+ pme.pmBootLoad = htobe32(0x4000);
+ pme.pmBootEntry = htobe32(0x4000);
+ strlcpy(pme.pmProcessor, "PowerPC", sizeof(pme.pmProcessor));
+ if (pwrite(params->fsfd, &pme, MACPPC_BOOT_BLOCK_BLOCKSIZE,
+ 2 * MACPPC_BOOT_BLOCK_BLOCKSIZE) != MACPPC_BOOT_BLOCK_BLOCKSIZE) {
+ warn("Can't write Apple Partition Map into sector 2 of `%s'",
+ params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
--- /dev/null
+/* $NetBSD: news.c,v 1.7 2008/04/28 20:24:16 martin Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn and Izumi Tsutsui.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: news.c,v 1.7 2008/04/28 20:24:16 martin Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static int news_copydisklabel(ib_params *, struct bbinfo_params *, uint8_t *);
+
+static int news68k_clearboot(ib_params *);
+static int news68k_setboot(ib_params *);
+static int newsmips_clearboot(ib_params *);
+static int newsmips_setboot(ib_params *);
+
+struct ib_mach ib_mach_news68k =
+ { "news68k", news68k_setboot, news68k_clearboot, no_editboot,
+ IB_STAGE2START };
+
+struct ib_mach ib_mach_newsmips =
+ { "newsmips", newsmips_setboot, newsmips_clearboot, no_editboot,
+ IB_STAGE2START };
+
+/*
+ * news68k specific support
+ */
+
+static struct bbinfo_params news68k_bbparams = {
+ NEWS68K_BBINFO_MAGIC,
+ NEWS_BOOT_BLOCK_OFFSET, /* write all 8K (including disklabel) */
+ NEWS_BOOT_BLOCK_BLOCKSIZE,
+ NEWS_BOOT_BLOCK_MAX_SIZE,
+ 0,
+ BBINFO_BIG_ENDIAN,
+};
+
+static int
+news68k_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_clearboot(params, &news68k_bbparams,
+ news_copydisklabel));
+}
+
+static int
+news68k_setboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_setboot(params, &news68k_bbparams,
+ news_copydisklabel));
+}
+
+
+/*
+ * newsmips specific support
+ */
+
+static struct bbinfo_params newsmips_bbparams = {
+ NEWSMIPS_BBINFO_MAGIC,
+ NEWS_BOOT_BLOCK_OFFSET, /* write all 8K (including disklabel) */
+ NEWS_BOOT_BLOCK_BLOCKSIZE,
+ NEWS_BOOT_BLOCK_MAX_SIZE,
+ 0,
+ BBINFO_BIG_ENDIAN,
+};
+
+static int
+newsmips_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_clearboot(params, &newsmips_bbparams,
+ news_copydisklabel));
+}
+
+static int
+newsmips_setboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_setboot(params, &newsmips_bbparams,
+ news_copydisklabel));
+}
+
+
+/*
+ * news_copydisklabel --
+ * copy disklabel from existing location on disk into bootstrap,
+ * as the primary bootstrap contains the disklabel.
+ */
+static int
+news_copydisklabel(ib_params *params, struct bbinfo_params *bbparams,
+ uint8_t *bb)
+{
+ uint8_t boot00[NEWS_BOOT_BLOCK_BLOCKSIZE];
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(bbparams != NULL);
+ assert(bb != NULL);
+
+ /* Read label sector to copy disklabel from */
+ memset(boot00, 0, sizeof(boot00));
+ rv = pread(params->fsfd, boot00, sizeof(boot00), 0);
+ if (rv == -1) {
+ warn("Reading label sector from `%s'", params->filesystem);
+ return (0);
+ }
+ /* Copy disklabel */
+ memcpy(bb + NEWS_BOOT_BLOCK_LABELOFFSET,
+ boot00 + NEWS_BOOT_BLOCK_LABELOFFSET,
+ sizeof(boot00) - NEWS_BOOT_BLOCK_LABELOFFSET);
+
+ return (1);
+}
--- /dev/null
+/* $NetBSD: next68k.c,v 1.7 2010/01/07 13:26:00 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight and Christian Limpach.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: next68k.c,v 1.7 2010/01/07 13:26:00 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <md5.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static uint16_t nextstep_checksum(const void *, const void *);
+static int next68k_setboot(ib_params *);
+
+struct ib_mach ib_mach_next68k =
+ { "next68k", next68k_setboot, no_clearboot, no_editboot, 0};
+
+static uint16_t
+nextstep_checksum(const void *vbuf, const void *vlimit)
+{
+ const uint16_t *buf = vbuf;
+ const uint16_t *limit = vlimit;
+ u_int sum = 0;
+
+ while (buf < limit) {
+ sum += be16toh(*buf++);
+ }
+ sum += (sum >> 16);
+ return (sum & 0xffff);
+}
+
+static int
+next68k_setboot(ib_params *params)
+{
+ int retval, labelupdated;
+ uint8_t *bootbuf;
+ size_t bootsize;
+ ssize_t rv;
+ uint32_t cd_secsize;
+ int sec_netonb_mult;
+ struct next68k_disklabel *next68klabel;
+ uint16_t *checksum;
+ uint32_t fp, b0, b1;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ retval = 0;
+ labelupdated = 0;
+ bootbuf = NULL;
+
+ next68klabel = malloc(NEXT68K_LABEL_SIZE);
+ if (next68klabel == NULL) {
+ warn("Allocating %lu bytes", (unsigned long)NEXT68K_LABEL_SIZE);
+ goto done;
+ }
+
+ /*
+ * Read in the next68k disklabel
+ */
+ rv = pread(params->fsfd, next68klabel, NEXT68K_LABEL_SIZE,
+ NEXT68K_LABEL_SECTOR * params->sectorsize + NEXT68K_LABEL_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ }
+ if (rv != NEXT68K_LABEL_SIZE) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+ if (be32toh(next68klabel->cd_version) == NEXT68K_LABEL_CD_V3) {
+ checksum = &next68klabel->NEXT68K_LABEL_cd_v3_checksum;
+ } else {
+ checksum = &next68klabel->cd_checksum;
+ }
+ if (nextstep_checksum (next68klabel, checksum) !=
+ be16toh(*checksum)) {
+ warn("Disklabel checksum invalid on `%s'",
+ params->filesystem);
+ goto done;
+ }
+
+ cd_secsize = be32toh(next68klabel->cd_secsize);
+ sec_netonb_mult = (cd_secsize / params->sectorsize);
+
+ /*
+ * Allocate a buffer, with space to round up the input file
+ * to the next block size boundary, and with space for the boot
+ * block.
+ */
+ bootsize = roundup(params->s1stat.st_size, cd_secsize);
+
+ bootbuf = malloc(bootsize);
+ if (bootbuf == NULL) {
+ warn("Allocating %zu bytes", bootsize);
+ goto done;
+ }
+ memset(bootbuf, 0, bootsize);
+
+ /*
+ * Read the file into the buffer.
+ */
+ rv = pread(params->s1fd, bootbuf, params->s1stat.st_size, 0);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ } else if (rv != params->s1stat.st_size) {
+ warnx("Reading `%s': short read", params->stage1);
+ goto done;
+ }
+
+ if (bootsize > be16toh(next68klabel->cd_front) * cd_secsize -
+ NEXT68K_LABEL_SIZE) {
+ warnx("Boot program is larger than front porch space");
+ goto done;
+ }
+
+ fp = be16toh(next68klabel->cd_front);
+ b0 = be32toh(next68klabel->cd_boot_blkno[0]);
+ b1 = be32toh(next68klabel->cd_boot_blkno[1]);
+
+ if (b0 > fp)
+ b0 = fp;
+ if (b1 > fp)
+ b1 = fp;
+ if (((bootsize / cd_secsize) > b1 - b0) ||
+ ((bootsize / cd_secsize) > fp - b1)) {
+ if (2 * bootsize > (fp * cd_secsize - NEXT68K_LABEL_SIZE))
+ /* can only fit one copy */
+ b0 = b1 = NEXT68K_LABEL_SIZE / cd_secsize;
+ else {
+ if (2 * bootsize > (fp * cd_secsize -
+ NEXT68K_LABEL_DEFAULTBOOT0_1 *
+ params->sectorsize))
+ /* can fit two copies starting after label */
+ b0 = NEXT68K_LABEL_SIZE / cd_secsize;
+ else
+ /* can fit two copies starting at default 1 */
+ b0 = NEXT68K_LABEL_DEFAULTBOOT0_1 /
+ sec_netonb_mult;
+ /* try to fit 2nd copy at default 2 */
+ b1 = NEXT68K_LABEL_DEFAULTBOOT0_2 / sec_netonb_mult;
+ if (fp < b1)
+ b1 = fp;
+ if (bootsize / cd_secsize > (fp - b1))
+ /* fit 2nd copy before front porch */
+ b1 = fp - bootsize / cd_secsize;
+ }
+ }
+ if (next68klabel->cd_boot_blkno[0] != (int32_t)htobe32(b0)) {
+ next68klabel->cd_boot_blkno[0] = htobe32(b0);
+ labelupdated = 1;
+ }
+ if (next68klabel->cd_boot_blkno[1] != (int32_t)htobe32(b1)) {
+ next68klabel->cd_boot_blkno[1] = htobe32(b1);
+ labelupdated = 1;
+ }
+ if (params->flags & IB_VERBOSE)
+ printf("Boot programm locations%s: %d %d\n",
+ labelupdated ? " updated" : "", b0 * sec_netonb_mult,
+ b1 * sec_netonb_mult);
+
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ /*
+ * Write the updated next68k disklabel
+ */
+ if (labelupdated) {
+ if (params->flags & IB_VERBOSE)
+ printf ("Writing updated label\n");
+ *checksum = htobe16(nextstep_checksum (next68klabel,
+ checksum));
+ rv = pwrite(params->fsfd, next68klabel, NEXT68K_LABEL_SIZE,
+ NEXT68K_LABEL_SECTOR * params->sectorsize +
+ NEXT68K_LABEL_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ }
+ if (rv != NEXT68K_LABEL_SIZE) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+ }
+
+ b0 *= sec_netonb_mult;
+ b1 *= sec_netonb_mult;
+
+ /*
+ * Write boot program to locations b0 and b1 (if different).
+ */
+ for (;;) {
+ if (params->flags & IB_VERBOSE)
+ printf ("Writing boot program at %d\n", b0);
+ rv = pwrite(params->fsfd, bootbuf, bootsize,
+ b0 * params->sectorsize);
+ if (rv == -1) {
+ warn("Writing `%s' at %d", params->filesystem, b0);
+ goto done;
+ }
+ if ((size_t)rv != bootsize) {
+ warnx("Writing `%s' at %d: short write",
+ params->filesystem, b0);
+ goto done;
+ }
+ if (b0 == b1)
+ break;
+ b0 = b1;
+ }
+
+ retval = 1;
+
+ done:
+ if (bootbuf)
+ free(bootbuf);
+ if (next68klabel)
+ free(next68klabel);
+ return retval;
+}
--- /dev/null
+/* $NetBSD: pmax.c,v 1.14 2009/04/05 11:55:39 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Simon Burge.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Ross Harvey. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ross Harvey
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: pmax.c,v 1.14 2009/04/05 11:55:39 lukem Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/exec_elf.h>
+
+#include "installboot.h"
+
+static int load_bootstrap(ib_params *, char **,
+ uint32_t *, uint32_t *, size_t *);
+
+static int pmax_clearboot(ib_params *);
+static int pmax_setboot(ib_params *);
+
+struct ib_mach ib_mach_pmax =
+ { "pmax", pmax_setboot, pmax_clearboot, no_editboot,
+ IB_STAGE1START | IB_APPEND | IB_SUNSUM };
+
+
+static int
+pmax_clearboot(ib_params *params)
+{
+ struct pmax_boot_block bb;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
+
+ rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ return (0);
+ }
+
+ if (le32toh(bb.magic) != PMAX_BOOT_MAGIC) {
+ warnx(
+ "Old boot block magic number invalid; boot block invalid");
+ return (0);
+ }
+
+ bb.map[0].num_blocks = bb.map[0].start_block = bb.mode = 0;
+ bb.magic = htole32(PMAX_BOOT_MAGIC);
+
+ if (params->flags & IB_SUNSUM) {
+ uint16_t sum;
+
+ sum = compute_sunsum((uint16_t *)&bb);
+ if (! set_sunsum(params, (uint16_t *)&bb, sum))
+ return (0);
+ }
+
+ if (params->flags & IB_VERBOSE)
+ printf("%slearing boot block\n",
+ (params->flags & IB_NOWRITE) ? "Not c" : "C");
+ if (params->flags & IB_NOWRITE)
+ return (1);
+
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+pmax_setboot(ib_params *params)
+{
+ struct pmax_boot_block bb;
+ uint32_t startblock;
+ int retval;
+ char *bootstrapbuf;
+ size_t bootstrapsize;
+ uint32_t bootstrapload, bootstrapexec;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+ assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
+
+ retval = 0;
+ bootstrapbuf = NULL;
+
+ if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
+ &bootstrapexec, &bootstrapsize))
+ goto done;
+
+ rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ /* fill in the updated boot block fields */
+ if (params->flags & IB_APPEND) {
+ if (! S_ISREG(params->fsstat.st_mode)) {
+ warnx(
+ "`%s' must be a regular file to append a bootstrap",
+ params->filesystem);
+ goto done;
+ }
+ startblock = howmany(params->fsstat.st_size,
+ PMAX_BOOT_BLOCK_BLOCKSIZE);
+ } else if (params->flags & IB_STAGE1START) {
+ startblock = params->s1start;
+ } else {
+ startblock = PMAX_BOOT_BLOCK_OFFSET / PMAX_BOOT_BLOCK_BLOCKSIZE
+ + 1;
+ }
+
+ bb.map[0].start_block = htole32(startblock);
+ bb.map[0].num_blocks =
+ htole32(howmany(bootstrapsize, PMAX_BOOT_BLOCK_BLOCKSIZE));
+ bb.magic = htole32(PMAX_BOOT_MAGIC);
+ bb.load_addr = htole32(bootstrapload);
+ bb.exec_addr = htole32(bootstrapexec);
+ bb.mode = htole32(PMAX_BOOTMODE_CONTIGUOUS);
+
+ if (params->flags & IB_SUNSUM) {
+ uint16_t sum;
+
+ sum = compute_sunsum((uint16_t *)&bb);
+ if (! set_sunsum(params, (uint16_t *)&bb, sum))
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %u\n",
+ le32toh(bb.map[0].start_block));
+ printf("Bootstrap sector count: %u\n",
+ le32toh(bb.map[0].num_blocks));
+ printf("Bootstrap load address: %#x\n",
+ le32toh(bb.load_addr));
+ printf("Bootstrap exec address: %#x\n",
+ le32toh(bb.exec_addr));
+ printf("%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+ rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
+ startblock * PMAX_BOOT_BLOCK_BLOCKSIZE);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if ((size_t)rv != bootstrapsize) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE)
+ printf("Writing boot block\n");
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else {
+ retval = 1;
+ }
+
+ done:
+ if (bootstrapbuf)
+ free(bootstrapbuf);
+ return (retval);
+}
+
+
+#define MAX_SEGMENTS 10 /* We can load up to 10 segments */
+
+struct seglist {
+ Elf32_Addr addr;
+ Elf32_Off f_offset;
+ Elf32_Word f_size;
+};
+
+static int
+load_bootstrap(ib_params *params, char **data,
+ uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
+{
+ int i, nsegs;
+ Elf32_Addr lowaddr, highaddr;
+ Elf32_Ehdr ehdr;
+ Elf32_Phdr phdr;
+ struct seglist seglist[MAX_SEGMENTS];
+
+ if ((pread(params->s1fd, &ehdr, sizeof(ehdr), 0)) != sizeof(ehdr)) {
+ warn("Reading `%s'", params->stage1);
+ return (0);
+ }
+ if ((memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) ||
+ (ehdr.e_ident[EI_CLASS] != ELFCLASS32)) {
+ warnx("No ELF header in `%s'", params->stage1);
+ return (0);
+ }
+
+ nsegs = highaddr = 0;
+ lowaddr = (uint32_t) ULONG_MAX;
+
+ for (i = 0; i < le16toh(ehdr.e_phnum); i++) {
+ if (pread(params->s1fd, &phdr, sizeof(phdr),
+ (off_t) le32toh(ehdr.e_phoff) + i * sizeof(phdr))
+ != sizeof(phdr)) {
+ warn("Reading `%s'", params->stage1);
+ return (0);
+ }
+ if (le32toh(phdr.p_type) != PT_LOAD)
+ continue;
+
+ seglist[nsegs].addr = le32toh(phdr.p_paddr);
+ seglist[nsegs].f_offset = le32toh(phdr.p_offset);
+ seglist[nsegs].f_size = le32toh(phdr.p_filesz);
+ nsegs++;
+
+ if (le32toh(phdr.p_paddr) < lowaddr)
+ lowaddr = le32toh(phdr.p_paddr);
+ if (le32toh(phdr.p_paddr) + le32toh(phdr.p_filesz) > highaddr)
+ highaddr = le32toh(phdr.p_paddr) +
+ le32toh(phdr.p_filesz);
+ }
+
+ *loadaddr = lowaddr;
+ *execaddr = le32toh(ehdr.e_entry);
+ *len = roundup(highaddr - lowaddr, PMAX_BOOT_BLOCK_BLOCKSIZE);
+ if ((*data = malloc(*len)) == NULL) {
+ warn("Allocating %lu bytes", (unsigned long) *len);
+ return (0);
+ }
+
+ /* Now load the bootstrap into memory */
+ for (i = 0; i < nsegs; i++) {
+ if ((Elf32_Word)pread(params->s1fd,
+ *data + seglist[i].addr - lowaddr,
+ seglist[i].f_size, (off_t)seglist[i].f_offset)
+ != seglist[i].f_size) {
+ warn("Reading `%s'", params->stage1);
+ return (0);
+ }
+ }
+ return (1);
+}
--- /dev/null
+/* $NetBSD: sparc.c,v 1.11 2008/04/28 20:24:16 martin Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg and Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: sparc.c,v 1.11 2008/04/28 20:24:16 martin Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static struct bbinfo_params bbparams = {
+ SPARC_BBINFO_MAGIC,
+ SPARC_BOOT_BLOCK_OFFSET,
+ SPARC_BOOT_BLOCK_BLOCKSIZE,
+ SPARC_BOOT_BLOCK_MAX_SIZE,
+ 32, /* leave room for a.out header */
+ BBINFO_BIG_ENDIAN,
+};
+
+static int sparc_clearheader(ib_params *, struct bbinfo_params *, uint8_t *);
+static int sparc_setheader(ib_params *, struct bbinfo_params *, uint8_t *);
+
+static int sparc_clearboot(ib_params *);
+static int sparc_setboot(ib_params *);
+
+struct ib_mach ib_mach_sparc =
+ { "sparc", sparc_setboot, sparc_clearboot, no_editboot,
+ IB_STAGE2START };
+
+static int
+sparc_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_clearboot(params, &bbparams, sparc_clearheader));
+}
+
+static int
+sparc_setboot(ib_params *params)
+{
+ assert(params != NULL);
+
+ return (shared_bbinfo_setboot(params, &bbparams, sparc_setheader));
+}
+
+
+static int
+sparc_clearheader(ib_params *params, struct bbinfo_params *bb_params,
+ uint8_t *bb)
+{
+
+ assert(params != NULL);
+ assert(bb_params != NULL);
+ assert(bb != NULL);
+
+ memset(bb, 0, bb_params->headeroffset);
+ return (1);
+}
+
+static int
+sparc_setheader(ib_params *params, struct bbinfo_params *bb_params, uint8_t *bb)
+{
+
+ assert(params != NULL);
+ assert(bb_params != NULL);
+ assert(bb != NULL);
+
+ /*
+ * sun4c/sun4m PROMs require an a.out(5) format header.
+ * Old-style sun4 PROMs do not expect a header at all.
+ * To deal with this, we construct a header that is also executable
+ * code containing a forward branch that gets us past the 32-byte
+ * header where the actual code begins. In assembly:
+ * .word MAGIC ! a NOP
+ * ba,a start !
+ * .skip 24 ! pad
+ * start:
+ */
+#define SUN_MAGIC 0x01030107
+#define SUN4_BASTART 0x30800007 /* i.e.: ba,a `start' */
+ *((uint32_t *)bb) = htobe32(SUN_MAGIC);
+ *((uint32_t *)bb + 1) = htobe32(SUN4_BASTART);
+
+ return (1);
+}
--- /dev/null
+/* $NetBSD: sparc64.c,v 1.18 2010/01/14 16:27:49 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2002 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: sparc64.c,v 1.18 2010/01/14 16:27:49 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static int sparc64_clearboot(ib_params *);
+static int sparc64_setboot(ib_params *);
+
+struct ib_mach ib_mach_sparc64 =
+ { "sparc64", sparc64_setboot, sparc64_clearboot, no_editboot, 0};
+
+static int
+sparc64_clearboot(ib_params *params)
+{
+ char bb[SPARC64_BOOT_BLOCK_MAX_SIZE];
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+
+ if (params->flags & (IB_STAGE1START | IB_STAGE2START)) {
+ warnx("`-b bno' and `-B bno' are not supported for %s",
+ params->machine->name);
+ return (0);
+ }
+
+ /* first check that it _could_ exist here */
+ rv = pread(params->fsfd, &bb, sizeof(bb), SPARC64_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ return (0);
+ }
+
+ /* now clear it out to nothing */
+ memset(&bb, 0, sizeof(bb));
+
+ if (params->flags & IB_VERBOSE)
+ printf("%slearing boot block\n",
+ (params->flags & IB_NOWRITE) ? "Not c" : "C");
+ if (params->flags & IB_NOWRITE)
+ return (1);
+
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), SPARC64_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+sparc64_setboot(ib_params *params)
+{
+ char bb[SPARC64_BOOT_BLOCK_MAX_SIZE];
+ int retval;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ retval = 0;
+
+ if (params->flags & (IB_STAGE1START | IB_STAGE2START)) {
+ warnx("`-b bno' and `-B bno' are not supported for %s",
+ params->machine->name);
+ goto done;
+ }
+
+ memset(&bb, 0, SPARC64_BOOT_BLOCK_MAX_SIZE);
+ rv = read(params->s1fd, &bb, sizeof(bb));
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %u\n",
+ SPARC64_BOOT_BLOCK_OFFSET / SPARC64_BOOT_BLOCK_BLOCKSIZE);
+ printf("Bootstrap byte count: %u\n", (unsigned)rv);
+ printf("%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ rv = pwrite(params->fsfd, &bb, SPARC64_BOOT_BLOCK_MAX_SIZE,
+ SPARC64_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != SPARC64_BOOT_BLOCK_MAX_SIZE) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else
+ retval = 1;
+
+ done:
+ return (retval);
+}
--- /dev/null
+/* $NetBSD: sun68k.c,v 1.21 2008/04/28 20:24:16 martin Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: sun68k.c,v 1.21 2008/04/28 20:24:16 martin Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+
+#include "installboot.h"
+
+static int sun68k_clearboot(ib_params *);
+static int sun68k_setboot(ib_params *);
+
+struct ib_mach ib_mach_sun2 =
+ { "sun2", sun68k_setboot, sun68k_clearboot, no_editboot,
+ IB_STAGE2START };
+
+struct ib_mach ib_mach_sun3 =
+ { "sun3", sun68k_setboot, sun68k_clearboot, no_editboot,
+ IB_STAGE2START };
+
+static struct bbinfo_params bbparams = {
+ SUN68K_BBINFO_MAGIC,
+ SUN68K_BOOT_BLOCK_OFFSET,
+ SUN68K_BOOT_BLOCK_BLOCKSIZE,
+ SUN68K_BOOT_BLOCK_MAX_SIZE,
+ 0,
+ BBINFO_BIG_ENDIAN,
+};
+
+static int
+sun68k_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_clearboot(params, &bbparams, NULL));
+}
+
+static int
+sun68k_setboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ return (shared_bbinfo_setboot(params, &bbparams, NULL));
+}
--- /dev/null
+/* $NetBSD: vax.c,v 1.13 2009/04/05 11:55:39 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Simon Burge.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: vax.c,v 1.13 2009/04/05 11:55:39 lukem Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static int load_bootstrap(ib_params *, char **,
+ uint32_t *, uint32_t *, size_t *);
+
+static int vax_clearboot(ib_params *);
+static int vax_setboot(ib_params *);
+
+struct ib_mach ib_mach_vax =
+ { "vax", vax_setboot, vax_clearboot, no_editboot,
+ IB_STAGE1START | IB_APPEND | IB_SUNSUM };
+
+static int
+vax_clearboot(ib_params *params)
+{
+ struct vax_boot_block bb;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(sizeof(struct vax_boot_block) == VAX_BOOT_BLOCK_BLOCKSIZE);
+
+ rv = pread(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ return (0);
+ }
+
+ if (bb.bb_id_offset * 2 != offsetof(struct vax_boot_block, bb_magic1)
+ || bb.bb_magic1 != VAX_BOOT_MAGIC1) {
+ warnx(
+ "Old boot block magic number invalid; boot block invalid");
+ return (0);
+ }
+
+ bb.bb_id_offset = 1;
+ bb.bb_mbone = 0;
+ bb.bb_lbn_hi = 0;
+ bb.bb_lbn_low = 0;
+
+ if (params->flags & IB_SUNSUM) {
+ uint16_t sum;
+
+ sum = compute_sunsum((uint16_t *)&bb);
+ if (! set_sunsum(params, (uint16_t *)&bb, sum))
+ return (0);
+ }
+
+ if (params->flags & IB_VERBOSE)
+ printf("%slearing boot block\n",
+ (params->flags & IB_NOWRITE) ? "Not c" : "C");
+ if (params->flags & IB_NOWRITE)
+ return (1);
+
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ return (0);
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+vax_setboot(ib_params *params)
+{
+ struct stat bootstrapsb;
+ struct vax_boot_block bb;
+ uint32_t startblock;
+ int retval;
+ char *bootstrapbuf;
+ size_t bootstrapsize;
+ uint32_t bootstrapload, bootstrapexec;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+ assert(sizeof(struct vax_boot_block) == VAX_BOOT_BLOCK_BLOCKSIZE);
+
+ retval = 0;
+ bootstrapbuf = NULL;
+
+ if (fstat(params->s1fd, &bootstrapsb) == -1) {
+ warn("Examining `%s'", params->stage1);
+ goto done;
+ }
+ if (!S_ISREG(bootstrapsb.st_mode)) {
+ warnx("`%s' must be a regular file", params->stage1);
+ goto done;
+ }
+ if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
+ &bootstrapexec, &bootstrapsize))
+ goto done;
+
+ rv = pread(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(bb)) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ /* fill in the updated boot block fields */
+ if (params->flags & IB_APPEND) {
+ struct stat filesyssb;
+
+ if (fstat(params->fsfd, &filesyssb) == -1) {
+ warn("Examining `%s'", params->filesystem);
+ goto done;
+ }
+ if (!S_ISREG(filesyssb.st_mode)) {
+ warnx(
+ "`%s' must be a regular file to append a bootstrap",
+ params->filesystem);
+ goto done;
+ }
+ startblock = howmany(filesyssb.st_size,
+ VAX_BOOT_BLOCK_BLOCKSIZE);
+ } else if (params->flags & IB_STAGE1START) {
+ startblock = params->s1start;
+ } else {
+ startblock = VAX_BOOT_BLOCK_OFFSET / VAX_BOOT_BLOCK_BLOCKSIZE
+ + 1;
+ }
+
+ bb.bb_id_offset = offsetof(struct vax_boot_block, bb_magic1) / 2;
+ bb.bb_mbone = 1;
+ bb.bb_lbn_hi = htole16((uint16_t) (startblock >> 16));
+ bb.bb_lbn_low = htole16((uint16_t) (startblock >> 0));
+ /*
+ * Now the identification block
+ */
+ bb.bb_magic1 = VAX_BOOT_MAGIC1;
+ bb.bb_mbz1 = 0;
+ bb.bb_sum1 = ~(bb.bb_magic1 + bb.bb_mbz1 + bb.bb_pad1);
+
+ bb.bb_mbz2 = 0;
+ bb.bb_volinfo = VAX_BOOT_VOLINFO_NONE;
+ bb.bb_pad2a = 0;
+ bb.bb_pad2b = 0;
+
+ bb.bb_size = htole32(bootstrapsize / VAX_BOOT_BLOCK_BLOCKSIZE);
+ bb.bb_load = htole32(VAX_BOOT_LOAD);
+ bb.bb_entry = htole32(VAX_BOOT_ENTRY);
+ bb.bb_sum3 = htole32(le32toh(bb.bb_size) + le32toh(bb.bb_load) \
+ + le32toh(bb.bb_entry));
+
+ if (params->flags & IB_SUNSUM) {
+ uint16_t sum;
+
+ sum = compute_sunsum((uint16_t *)&bb);
+ if (! set_sunsum(params, (uint16_t *)&bb, sum))
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %u\n", startblock);
+ printf("Bootstrap sector count: %u\n", le32toh(bb.bb_size));
+ printf("%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+ rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
+ startblock * VAX_BOOT_BLOCK_BLOCKSIZE);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if ((size_t)rv != bootstrapsize) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ }
+
+ if (params->flags & IB_VERBOSE)
+ printf("Writing boot block\n");
+ rv = pwrite(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof(bb)) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else {
+ retval = 1;
+ }
+
+ done:
+ if (bootstrapbuf)
+ free(bootstrapbuf);
+ return (retval);
+}
+
+static int
+load_bootstrap(ib_params *params, char **data,
+ uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
+{
+ ssize_t cc;
+ size_t buflen;
+
+ buflen = 512 * (VAX_BOOT_SIZE + 1);
+ *data = malloc(buflen);
+ if (*data == NULL) {
+ warn("Allocating %lu bytes", (unsigned long) buflen);
+ return (0);
+ }
+
+ cc = pread(params->s1fd, *data, buflen, 0);
+ if (cc <= 0) {
+ warn("Reading `%s'", params->stage1);
+ return (0);
+ }
+ if (cc > 512 * VAX_BOOT_SIZE) {
+ warnx("`%s': too large", params->stage1);
+ return (0);
+ }
+
+ *len = roundup(cc, VAX_BOOT_BLOCK_BLOCKSIZE);
+ *loadaddr = VAX_BOOT_LOAD;
+ *execaddr = VAX_BOOT_ENTRY;
+ return (1);
+}
--- /dev/null
+/* $NetBSD: x68k.c,v 1.4 2008/04/28 20:24:16 martin Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: x68k.c,v 1.4 2008/04/28 20:24:16 martin Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+#define X68K_LABELOFFSET 64
+#define X68K_LABELSIZE 404 /* reserve 16 partitions */
+
+static int x68k_clearheader(ib_params *, struct bbinfo_params *, uint8_t *);
+
+static int x68k_clearboot(ib_params *);
+static int x68k_setboot(ib_params *);
+
+struct ib_mach ib_mach_x68k =
+ { "x68k", x68k_setboot, x68k_clearboot, no_editboot,
+ IB_STAGE1START | IB_STAGE2START };
+
+static struct bbinfo_params bbparams = {
+ X68K_BBINFO_MAGIC,
+ X68K_BOOT_BLOCK_OFFSET,
+ X68K_BOOT_BLOCK_BLOCKSIZE,
+ X68K_BOOT_BLOCK_MAX_SIZE,
+ X68K_LABELOFFSET + X68K_LABELSIZE, /* XXX */
+ BBINFO_BIG_ENDIAN,
+};
+
+static int
+x68k_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ if (params->flags & IB_STAGE1START) {
+ warnx("`-b bno' is not supported for %s",
+ params->machine->name);
+ return 0;
+ }
+ return shared_bbinfo_clearboot(params, &bbparams, x68k_clearheader);
+}
+
+static int
+x68k_clearheader(ib_params *params, struct bbinfo_params *bb_params,
+ uint8_t *bb)
+{
+
+ assert(params != NULL);
+ assert(bb_params != NULL);
+ assert(bb != NULL);
+
+ memset(bb, 0, X68K_LABELOFFSET);
+ return 1;
+}
+
+static int
+x68k_setboot(ib_params *params)
+{
+ struct stat bootstrapsb;
+ char bb[X68K_BOOT_BLOCK_MAX_SIZE];
+ char label[X68K_LABELSIZE];
+ uint32_t s1start;
+ int retval;
+ ssize_t rv;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+
+ retval = 0;
+
+ if (params->flags & IB_STAGE1START)
+ s1start = params->s1start;
+ else
+ s1start = X68K_BOOT_BLOCK_OFFSET /
+ X68K_BOOT_BLOCK_BLOCKSIZE;
+
+ /* read disklabel on the target disk */
+ rv = pread(params->fsfd, label, sizeof label,
+ s1start * X68K_BOOT_BLOCK_BLOCKSIZE + X68K_LABELOFFSET);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if (rv != sizeof label) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ if (fstat(params->s1fd, &bootstrapsb) == -1) {
+ warn("Examining `%s'", params->stage1);
+ goto done;
+ }
+ if (!S_ISREG(bootstrapsb.st_mode)) {
+ warnx("`%s' must be a regular file", params->stage1);
+ goto done;
+ }
+
+ /* read boot loader */
+ memset(&bb, 0, sizeof bb);
+ rv = read(params->s1fd, &bb, sizeof bb);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ }
+ /* then, overwrite disklabel */
+ memcpy(&bb[X68K_LABELOFFSET], &label, sizeof label);
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %#x\n", s1start);
+ printf("Bootstrap byte count: %#x\n", (unsigned)rv);
+ printf("%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ /* write boot loader and disklabel into the target disk */
+ rv = pwrite(params->fsfd, &bb, X68K_BOOT_BLOCK_MAX_SIZE,
+ s1start * X68K_BOOT_BLOCK_BLOCKSIZE);
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if (rv != X68K_BOOT_BLOCK_MAX_SIZE) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else
+ retval = 1;
+
+ done:
+ return (retval);
+}
--- /dev/null
+/* $NetBSD: bbinfo.c,v 1.14 2009/04/05 11:55:39 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette, Paul Kranenburg, and Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: bbinfo.c,v 1.14 2009/04/05 11:55:39 lukem Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+#ifndef HAVE_NBTOOL_CONFIG_H
+#include <sys/ioctl.h>
+#include <sys/dkio.h>
+#include <errno.h>
+#endif
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+int
+shared_bbinfo_clearboot(ib_params *params, struct bbinfo_params *bbparams,
+ int (*callback)(ib_params *, struct bbinfo_params *, uint8_t *))
+{
+ uint8_t *bb;
+ ssize_t rv;
+ int retval;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(bbparams != NULL);
+ assert((strlen(bbparams->magic) + 1) == 32);
+
+ retval = 0;
+ if ((bb = malloc(bbparams->maxsize)) == NULL) {
+ warn("Allocating %lu bytes for bbinfo",
+ (unsigned long) bbparams->maxsize);
+ goto done;
+ }
+
+ /* First check that it _could_ exist here */
+ rv = pread(params->fsfd, bb, bbparams->maxsize, bbparams->offset);
+ if (rv == -1) {
+ warn("Reading `%s'", params->filesystem);
+ goto done;
+ } else if ((uint32_t)rv != bbparams->maxsize) {
+ warnx("Reading `%s': short read", params->filesystem);
+ goto done;
+ }
+
+ /* Now clear out (past the header offset) */
+ memset(bb + bbparams->headeroffset, 0,
+ bbparams->maxsize - bbparams->headeroffset);
+ if (callback != NULL && ! (*callback)(params, bbparams, bb))
+ goto done;
+
+ if (params->flags & IB_VERBOSE)
+ printf("%slearing boot block\n",
+ (params->flags & IB_NOWRITE) ? "Not c" : "C");
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ rv = pwrite(params->fsfd, bb, bbparams->maxsize, bbparams->offset);
+#ifdef DIOCWLABEL
+ if (rv == -1 && errno == EROFS) {
+ /*
+ * The first sector might be protected by
+ * bounds_check_with_label(9)
+ */
+ int enable;
+
+ enable = 1;
+ rv = ioctl(params->fsfd, DIOCWLABEL, &enable);
+ if (rv != 0) {
+ warn("Cannot enable writes to the label sector");
+ goto done;
+ }
+
+ rv = pwrite(params->fsfd, bb, bbparams->maxsize,
+ bbparams->offset);
+
+ /* Reset write-protect. */
+ enable = 0;
+ (void)ioctl(params->fsfd, DIOCWLABEL, &enable);
+ }
+#endif
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if ((uint32_t)rv != bbparams->maxsize) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else
+ retval = 1;
+
+ done:
+ if (bb != NULL)
+ free(bb);
+ return (retval);
+}
+
+int
+shared_bbinfo_setboot(ib_params *params, struct bbinfo_params *bbparams,
+ int (*callback)(ib_params *, struct bbinfo_params *, uint8_t *))
+{
+ uint8_t *bb;
+ int retval;
+ ssize_t rv;
+ size_t bbi;
+ struct shared_bbinfo *bbinfop; /* bbinfo in prototype image */
+ uint32_t maxblk, nblk, blk_i;
+ ib_block *blocks;
+
+ assert(params != NULL);
+ assert(params->fsfd != -1);
+ assert(params->filesystem != NULL);
+ assert(params->fstype != NULL);
+ assert(params->s1fd != -1);
+ assert(params->stage1 != NULL);
+ assert(bbparams != NULL);
+ assert((strlen(bbparams->magic) + 1) == 32);
+
+ bbinfop = NULL; /* XXXGCC -Wuninitialized [sparc64] */
+ retval = 0;
+ blocks = NULL;
+ if ((bb = malloc(bbparams->maxsize)) == NULL) {
+ warn("Allocating %lu bytes for bbinfo",
+ (unsigned long) bbparams->maxsize);
+ goto done;
+ }
+
+ if (params->stage2 == NULL) {
+ warnx("Name of secondary bootstrap not provided");
+ goto done;
+ }
+
+ if (params->s1stat.st_size >
+ bbparams->maxsize - bbparams->headeroffset) {
+ warnx("`%s' cannot be larger than %lu bytes",
+ params->stage1, (unsigned long)(bbparams->maxsize -
+ bbparams->headeroffset));
+ goto done;
+ }
+
+ memset(bb, 0, bbparams->maxsize);
+ rv = read(params->s1fd, bb + bbparams->headeroffset,
+ bbparams->maxsize - bbparams->headeroffset);
+ if (rv == -1) {
+ warn("Reading `%s'", params->stage1);
+ goto done;
+ }
+
+ /*
+ * Quick sanity check that the bootstrap given
+ * is *not* an ELF executable.
+ */
+ if (memcmp(bb + bbparams->headeroffset + 1, "ELF", strlen("ELF"))
+ == 0) {
+ warnx("`%s' is an ELF executable; need raw binary",
+ params->stage1);
+ goto done;
+ }
+
+#define HOSTTOTARGET32(x) ((bbparams->endian == BBINFO_LITTLE_ENDIAN) \
+ ? (uint32_t)htole32((x)) : (uint32_t)htobe32((x)))
+#define TARGET32TOHOST(x) ((bbparams->endian == BBINFO_LITTLE_ENDIAN) \
+ ? (uint32_t)le32toh((x)) : (uint32_t)be32toh((x)))
+
+ /* Look for the bbinfo structure. */
+ bbinfop = NULL;
+ for (bbi = 0; bbi < bbparams->maxsize; bbi += sizeof(uint32_t)) {
+ bbinfop = (void *) (bb + bbparams->headeroffset + bbi);
+ if (memcmp(bbinfop->bbi_magic, bbparams->magic,
+ sizeof(bbinfop->bbi_magic)) == 0)
+ break;
+ }
+ if (bbi >= bbparams->maxsize) {
+ warnx("%s bbinfo structure not found in `%s'",
+ params->machine->name, params->stage1);
+ goto done;
+ }
+ maxblk = TARGET32TOHOST(bbinfop->bbi_block_count);
+ if (maxblk == 0 || maxblk > (bbparams->maxsize / sizeof(uint32_t))) {
+ warnx("%s bbinfo structure in `%s' has preposterous size `%u'",
+ params->machine->name, params->stage1, maxblk);
+ goto done;
+ }
+
+ /* Allocate space for our block list. */
+ blocks = malloc(sizeof(*blocks) * maxblk);
+ if (blocks == NULL) {
+ warn("Allocating %lu bytes",
+ (unsigned long)sizeof(*blocks) * maxblk);
+ goto done;
+ }
+
+ if (S_ISREG(params->fsstat.st_mode)) {
+ if (fsync(params->fsfd) == -1)
+ warn("Synchronising file system `%s'",
+ params->filesystem);
+ } else {
+ /* Ensure the secondary bootstrap is on disk. */
+ sync();
+ }
+
+ /* Collect the blocks for the secondary bootstrap. */
+ nblk = maxblk;
+ if (! params->fstype->findstage2(params, &nblk, blocks))
+ goto done;
+ if (nblk == 0) {
+ warnx("Secondary bootstrap `%s' is empty",
+ params->stage2);
+ goto done;
+ }
+
+ /* Save those blocks in the primary bootstrap. */
+ bbinfop->bbi_block_count = HOSTTOTARGET32(nblk);
+ bbinfop->bbi_block_size = HOSTTOTARGET32(blocks[0].blocksize);
+ for (blk_i = 0; blk_i < nblk; blk_i++) {
+ bbinfop->bbi_block_table[blk_i] =
+ HOSTTOTARGET32(blocks[blk_i].block);
+ if (blocks[blk_i].blocksize < blocks[0].blocksize &&
+ blk_i + 1 != nblk) {
+ warnx("Secondary bootstrap `%s' blocks do not have "
+ "a uniform size", params->stage2);
+ goto done;
+ }
+ }
+ if (callback != NULL && ! (*callback)(params, bbparams, bb))
+ goto done;
+
+ if (params->flags & IB_VERBOSE) {
+ printf("Bootstrap start sector: %u\n",
+ bbparams->offset / bbparams->blocksize);
+ printf("Bootstrap byte count: %u\n", (unsigned)rv);
+ printf("Bootstrap block table: "
+ "%u entries of %u bytes available, %u used:",
+ maxblk, blocks[0].blocksize, nblk);
+ for (blk_i = 0; blk_i < nblk; blk_i++)
+ printf(" %llu",
+ (unsigned long long)blocks[blk_i].block);
+ printf("\n%sriting bootstrap\n",
+ (params->flags & IB_NOWRITE) ? "Not w" : "W");
+ }
+ if (params->flags & IB_NOWRITE) {
+ retval = 1;
+ goto done;
+ }
+
+ rv = pwrite(params->fsfd, bb, bbparams->maxsize, bbparams->offset);
+#ifdef DIOCWLABEL
+ if (rv == -1 && errno == EROFS) {
+ /*
+ * The first sector might be protected by
+ * bounds_check_with_label(9)
+ */
+ int enable;
+
+ enable = 1;
+ rv = ioctl(params->fsfd, DIOCWLABEL, &enable);
+ if (rv != 0) {
+ warn("Cannot enable writes to the label sector");
+ goto done;
+ }
+
+ rv = pwrite(params->fsfd, bb, bbparams->maxsize,
+ bbparams->offset);
+
+ /* Reset write-protect. */
+ enable = 0;
+ (void)ioctl(params->fsfd, DIOCWLABEL, &enable);
+ }
+#endif
+ if (rv == -1) {
+ warn("Writing `%s'", params->filesystem);
+ goto done;
+ } else if ((uint32_t)rv != bbparams->maxsize) {
+ warnx("Writing `%s': short write", params->filesystem);
+ goto done;
+ } else {
+ retval = 1;
+ }
+
+ done:
+ if (blocks != NULL)
+ free(blocks);
+ if (bb != NULL)
+ free(bb);
+ return (retval);
+}
--- /dev/null
+/* $NetBSD: ext2fs.c,v 1.6 2010/01/14 16:27:49 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: ext2fs.c,v 1.6 2010/01/14 16:27:49 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#if !HAVE_NBTOOL_CONFIG_H
+#include <sys/mount.h>
+#endif
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+#include <ufs/ext2fs/ext2fs_dinode.h>
+#include <ufs/ext2fs/ext2fs_dir.h>
+#include <ufs/ext2fs/ext2fs.h>
+
+static int ext2fs_read_disk_block(ib_params *, uint64_t, int, uint8_t []);
+static int ext2fs_read_sblock(ib_params *, struct m_ext2fs *fs);
+static int ext2fs_read_gdblock(ib_params *, struct m_ext2fs *fs);
+static int ext2fs_find_disk_blocks(ib_params *, ino_t,
+ int (*)(ib_params *, void *, uint64_t, uint32_t), void *);
+static int ext2fs_findstage2_ino(ib_params *, void *, uint64_t, uint32_t);
+static int ext2fs_findstage2_blocks(ib_params *, void *, uint64_t,
+ uint32_t);
+
+
+/* This reads a disk block from the file system. */
+/* XXX: should be shared with ffs.c? */
+static int
+ext2fs_read_disk_block(ib_params *params, uint64_t blkno, int size,
+ uint8_t blk[])
+{
+ int rv;
+
+ assert(params != NULL);
+ assert(params->filesystem != NULL);
+ assert(params->fsfd != -1);
+ assert(size > 0);
+ assert(blk != NULL);
+
+ rv = pread(params->fsfd, blk, size, blkno * params->sectorsize);
+ if (rv == -1) {
+ warn("Reading block %llu in `%s'",
+ (unsigned long long)blkno, params->filesystem);
+ return 0;
+ } else if (rv != size) {
+ warnx("Reading block %llu in `%s': short read",
+ (unsigned long long)blkno, params->filesystem);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+ext2fs_read_sblock(ib_params *params, struct m_ext2fs *fs)
+{
+ uint8_t sbbuf[SBSIZE];
+
+ if (ext2fs_read_disk_block(params, SBOFF / params->sectorsize, SBSIZE,
+ sbbuf) == 0)
+
+ e2fs_sbload((void *)sbbuf, &fs->e2fs);
+
+ if (fs->e2fs.e2fs_magic != E2FS_MAGIC)
+ return 0;
+
+ if (fs->e2fs.e2fs_rev > E2FS_REV1 ||
+ (fs->e2fs.e2fs_rev == E2FS_REV1 &&
+ (fs->e2fs.e2fs_first_ino != EXT2_FIRSTINO ||
+ fs->e2fs.e2fs_inode_size != EXT2_DINODE_SIZE ||
+ (fs->e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) != 0)))
+ return 0;
+
+ fs->e2fs_ncg =
+ howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
+ fs->e2fs.e2fs_bpg);
+ /* XXX assume hw bsize = 512 */
+ fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
+ fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize;
+ fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
+ fs->e2fs_qbmask = fs->e2fs_bsize - 1;
+ fs->e2fs_bmask = ~fs->e2fs_qbmask;
+ fs->e2fs_ngdb =
+ howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd));
+ fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE;
+ fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
+
+ return 1;
+}
+
+static int
+ext2fs_read_gdblock(ib_params *params, struct m_ext2fs *fs)
+{
+ uint8_t gdbuf[MAXBSIZE];
+ uint32_t gdpb;
+ int i;
+
+ gdpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+
+ for (i = 0; i < fs->e2fs_ngdb; i++) {
+ if (ext2fs_read_disk_block(params, fsbtodb(fs,
+ fs->e2fs.e2fs_first_dblock + 1 /* superblock */ + i),
+ SBSIZE, gdbuf) == 0)
+ return 0;
+
+ e2fs_cgload((struct ext2_gd *)gdbuf, &fs->e2fs_gd[gdpb * i],
+ (i == (fs->e2fs_ngdb - 1)) ?
+ (fs->e2fs_ncg - gdpb * i) * sizeof(struct ext2_gd):
+ fs->e2fs_bsize);
+ }
+
+ return 1;
+}
+
+/*
+ * This iterates over the data blocks belonging to an inode,
+ * making a callback each iteration with the disk block number
+ * and the size.
+ */
+static int
+ext2fs_find_disk_blocks(ib_params *params, ino_t ino,
+ int (*callback)(ib_params *, void *, uint64_t, uint32_t),
+ void *state)
+{
+ uint8_t sbbuf[sizeof(struct m_ext2fs)];
+ struct m_ext2fs *fs;
+ uint8_t inodebuf[MAXBSIZE];
+ struct ext2fs_dinode inode_store, *inode;
+ int level_i;
+ int32_t blk, lblk, nblk;
+ int rv;
+#define LEVELS 4
+ struct {
+ uint32_t *blknums;
+ unsigned long blkcount;
+ uint8_t diskbuf[MAXBSIZE];
+ } level[LEVELS];
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+ assert(callback != NULL);
+ assert(state != NULL);
+
+ /* Read the superblock. */
+ fs = (void *)sbbuf;
+ if (ext2fs_read_sblock(params, fs) == 0)
+ return 0;
+
+ fs->e2fs_gd = malloc(sizeof(struct ext2_gd) * fs->e2fs_ncg);
+ if (fs->e2fs_gd == NULL) {
+ warnx("Can't allocate memofy for group descriptors");
+ return 0;
+ }
+
+ if (ext2fs_read_gdblock(params, fs) == 0) {
+ warnx("Can't read group descriptors");
+ return 0;
+ }
+
+ if (fs->e2fs_ipb <= 0) {
+ warnx("Bad ipb %d in superblock in `%s'",
+ fs->e2fs_ipb, params->filesystem);
+ return 0;
+ }
+
+ /* Read the inode. */
+ if (ext2fs_read_disk_block(params,
+ fsbtodb(fs, ino_to_fsba(fs, ino)) + params->fstype->offset,
+ fs->e2fs_bsize, inodebuf))
+ return 0;
+ inode = (void *)inodebuf;
+ e2fs_iload(&inode[ino_to_fsbo(fs, ino)], &inode_store);
+ inode = &inode_store;
+
+ /* Get the block count and initialize for our block walk. */
+ nblk = howmany(inode->e2di_size, fs->e2fs_bsize);
+ lblk = 0;
+ level_i = 0;
+ level[0].blknums = &inode->e2di_blocks[0];
+ level[0].blkcount = NDADDR;
+ level[1].blknums = &inode->e2di_blocks[NDADDR + 0];
+ level[1].blkcount = 1;
+ level[2].blknums = &inode->e2di_blocks[NDADDR + 1];
+ level[2].blkcount = 1;
+ level[3].blknums = &inode->e2di_blocks[NDADDR + 2];
+ level[3].blkcount = 1;
+
+ /* Walk the data blocks. */
+ while (nblk > 0) {
+
+ /*
+ * If there are no more blocks at this indirection
+ * level, move up one indirection level and loop.
+ */
+ if (level[level_i].blkcount == 0) {
+ if (++level_i == LEVELS)
+ break;
+ continue;
+ }
+
+ /* Get the next block at this level. */
+ blk = fs2h32(*(level[level_i].blknums++));
+ level[level_i].blkcount--;
+
+#if 0
+ fprintf(stderr, "ino %lu blk %lu level %d\n", ino, blk,
+ level_i);
+#endif
+
+ /*
+ * If we're not at the direct level, descend one
+ * level, read in that level's new block list,
+ * and loop.
+ */
+ if (level_i > 0) {
+ level_i--;
+ if (blk == 0)
+ memset(level[level_i].diskbuf, 0, MAXBSIZE);
+ else if (ext2fs_read_disk_block(params,
+ fsbtodb(fs, blk) + params->fstype->offset,
+ fs->e2fs_bsize, level[level_i].diskbuf) == 0)
+ return 0;
+ /* XXX ondisk32 */
+ level[level_i].blknums =
+ (uint32_t *)level[level_i].diskbuf;
+ level[level_i].blkcount = NINDIR(fs);
+ continue;
+ }
+
+ /* blk is the next direct level block. */
+#if 0
+ fprintf(stderr, "ino %lu db %lu blksize %lu\n", ino,
+ fsbtodb(fs, blk), sblksize(fs, inode->di_size, lblk));
+#endif
+ rv = (*callback)(params, state,
+ fsbtodb(fs, blk) + params->fstype->offset, fs->e2fs_bsize);
+ lblk++;
+ nblk--;
+ if (rv != 1)
+ return rv;
+ }
+
+ if (nblk != 0) {
+ warnx("Inode %llu in `%s' ran out of blocks?",
+ (unsigned long long)ino, params->filesystem);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * This callback reads a block of the root directory,
+ * searches for an entry for the secondary bootstrap,
+ * and saves the inode number if one is found.
+ */
+static int
+ext2fs_findstage2_ino(ib_params *params, void *_ino,
+ uint64_t blk, uint32_t blksize)
+{
+ uint8_t dirbuf[MAXBSIZE];
+ struct ext2fs_direct *de, *ede;
+ uint32_t ino;
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+ assert(params->stage2 != NULL);
+ assert(_ino != NULL);
+
+ /* Skip directory holes. */
+ if (blk == 0)
+ return 1;
+
+ /* Read the directory block. */
+ if (ext2fs_read_disk_block(params, blk, blksize, dirbuf) == 0)
+ return 0;
+
+ /* Loop over the directory entries. */
+ de = (struct ext2fs_direct *)&dirbuf[0];
+ ede = (struct ext2fs_direct *)&dirbuf[blksize];
+ while (de < ede) {
+ ino = fs2h32(de->e2d_ino);
+ if (ino != 0 && strcmp(de->e2d_name, params->stage2) == 0) {
+ *((uint32_t *)_ino) = ino;
+ return (2);
+ }
+ if (fs2h16(de->e2d_reclen) == 0)
+ break;
+ de = (struct ext2fs_direct *)((char *)de +
+ fs2h16(de->e2d_reclen));
+ }
+
+ return 1;
+}
+
+struct findblks_state {
+ uint32_t maxblk;
+ uint32_t nblk;
+ ib_block *blocks;
+};
+
+/* This callback records the blocks of the secondary bootstrap. */
+static int
+ext2fs_findstage2_blocks(ib_params *params, void *_state,
+ uint64_t blk, uint32_t blksize)
+{
+ struct findblks_state *state = _state;
+
+ assert(params != NULL);
+ assert(params->stage2 != NULL);
+ assert(_state != NULL);
+
+ if (state->nblk == state->maxblk) {
+ warnx("Secondary bootstrap `%s' has too many blocks (max %d)",
+ params->stage2, state->maxblk);
+ return (0);
+ }
+ state->blocks[state->nblk].block = blk;
+ state->blocks[state->nblk].blocksize = blksize;
+ state->nblk++;
+ return 1;
+}
+
+/*
+ * publicly visible functions
+ */
+
+int
+ext2fs_match(ib_params *params)
+{
+ uint8_t sbbuf[sizeof(struct m_ext2fs)];
+ struct m_ext2fs *fs;
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+
+ /* Read the superblock. */
+ fs = (void *)sbbuf;
+ if (ext2fs_read_sblock(params, fs) == 0)
+ return 0;
+
+ params->fstype->needswap = 0;
+ params->fstype->blocksize = fs->e2fs_bsize;
+ params->fstype->offset = 0;
+
+ return 1;
+}
+
+int
+ext2fs_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
+{
+ int rv;
+ uint32_t ino;
+ struct findblks_state state;
+
+ assert(params != NULL);
+ assert(params->stage2 != NULL);
+ assert(maxblk != NULL);
+ assert(blocks != NULL);
+
+ if (params->flags & IB_STAGE2START)
+ return hardcode_stage2(params, maxblk, blocks);
+
+ /* The secondary bootstrap must be clearly in /. */
+ if (params->stage2[0] == '/')
+ params->stage2++;
+ if (strchr(params->stage2, '/') != NULL) {
+ warnx("The secondary bootstrap `%s' must be in /",
+ params->stage2);
+ warnx("(Path must be relative to the file system in `%s')",
+ params->filesystem);
+ return 0;
+ }
+
+ /* Get the inode number of the secondary bootstrap. */
+ rv = ext2fs_find_disk_blocks(params, EXT2_ROOTINO,
+ ext2fs_findstage2_ino, &ino);
+ if (rv != 2) {
+ warnx("Could not find secondary bootstrap `%s' in `%s'",
+ params->stage2, params->filesystem);
+ warnx("(Path must be relative to the file system in `%s')",
+ params->filesystem);
+ return 0;
+ }
+
+ /* Record the disk blocks of the secondary bootstrap. */
+ state.maxblk = *maxblk;
+ state.nblk = 0;
+ state.blocks = blocks;
+ rv = ext2fs_find_disk_blocks(params, ino,
+ ext2fs_findstage2_blocks, &state);
+ if (rv == 0)
+ return 0;
+
+ *maxblk = state.nblk;
+ return 1;
+}
--- /dev/null
+/* $NetBSD: ffs.c,v 1.29 2010/01/14 16:27:49 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: ffs.c,v 1.29 2010/01/14 16:27:49 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/param.h>
+
+#if !HAVE_NBTOOL_CONFIG_H
+#include <sys/mount.h>
+#endif
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+/* From <dev/raidframe/raidframevar.h> */
+#define RF_PROTECTED_SECTORS 64L
+
+#undef DIRBLKSIZ
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
+#ifndef NO_FFS_SWAP
+#include <ufs/ufs/ufs_bswap.h>
+#else
+#define ffs_sb_swap(fs_a, fs_b)
+#define ffs_dinode1_swap(inode_a, inode_b)
+#define ffs_dinode2_swap(inode_a, inode_b)
+#endif
+
+static int ffs_match_common(ib_params *, off_t);
+static int ffs_read_disk_block(ib_params *, uint64_t, int, char []);
+static int ffs_find_disk_blocks_ufs1(ib_params *, ino_t,
+ int (*)(ib_params *, void *, uint64_t, uint32_t), void *);
+static int ffs_find_disk_blocks_ufs2(ib_params *, ino_t,
+ int (*)(ib_params *, void *, uint64_t, uint32_t), void *);
+static int ffs_findstage2_ino(ib_params *, void *, uint64_t, uint32_t);
+static int ffs_findstage2_blocks(ib_params *, void *, uint64_t, uint32_t);
+
+static int is_ufs2;
+
+
+/* This reads a disk block from the filesystem. */
+static int
+ffs_read_disk_block(ib_params *params, uint64_t blkno, int size, char blk[])
+{
+ int rv;
+
+ assert(params != NULL);
+ assert(params->filesystem != NULL);
+ assert(params->fsfd != -1);
+ assert(size > 0);
+ assert(blk != NULL);
+
+ rv = pread(params->fsfd, blk, size, blkno * params->sectorsize);
+ if (rv == -1) {
+ warn("Reading block %llu in `%s'",
+ (unsigned long long)blkno, params->filesystem);
+ return (0);
+ } else if (rv != size) {
+ warnx("Reading block %llu in `%s': short read",
+ (unsigned long long)blkno, params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+/*
+ * This iterates over the data blocks belonging to an inode,
+ * making a callback each iteration with the disk block number
+ * and the size.
+ */
+static int
+ffs_find_disk_blocks_ufs1(ib_params *params, ino_t ino,
+ int (*callback)(ib_params *, void *, uint64_t, uint32_t),
+ void *state)
+{
+ char sbbuf[SBLOCKSIZE];
+ struct fs *fs;
+ char inodebuf[MAXBSIZE];
+ struct ufs1_dinode *inode;
+ int level_i;
+ int32_t blk, lblk, nblk;
+ int rv;
+#define LEVELS 4
+ struct {
+ int32_t *blknums;
+ unsigned long blkcount;
+ char diskbuf[MAXBSIZE];
+ } level[LEVELS];
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+ assert(callback != NULL);
+ assert(state != NULL);
+
+ /* Read the superblock. */
+ if (!ffs_read_disk_block(params, params->fstype->sblockloc, SBLOCKSIZE,
+ sbbuf))
+ return (0);
+ fs = (struct fs *)sbbuf;
+#ifndef NO_FFS_SWAP
+ if (params->fstype->needswap)
+ ffs_sb_swap(fs, fs);
+#endif
+
+ if (fs->fs_inopb <= 0) {
+ warnx("Bad inopb %d in superblock in `%s'",
+ fs->fs_inopb, params->filesystem);
+ return (0);
+ }
+
+ /* Read the inode. */
+ if (! ffs_read_disk_block(params,
+ fsbtodb(fs, ino_to_fsba(fs, ino)) + params->fstype->offset,
+ fs->fs_bsize, inodebuf))
+ return (0);
+ inode = (struct ufs1_dinode *)inodebuf;
+ inode += ino_to_fsbo(fs, ino);
+#ifndef NO_FFS_SWAP
+ if (params->fstype->needswap)
+ ffs_dinode1_swap(inode, inode);
+#endif
+
+ /* Get the block count and initialize for our block walk. */
+ nblk = howmany(inode->di_size, fs->fs_bsize);
+ lblk = 0;
+ level_i = 0;
+ level[0].blknums = &inode->di_db[0];
+ level[0].blkcount = NDADDR;
+ level[1].blknums = &inode->di_ib[0];
+ level[1].blkcount = 1;
+ level[2].blknums = &inode->di_ib[1];
+ level[2].blkcount = 1;
+ level[3].blknums = &inode->di_ib[2];
+ level[3].blkcount = 1;
+
+ /* Walk the data blocks. */
+ while (nblk > 0) {
+
+ /*
+ * If there are no more blocks at this indirection
+ * level, move up one indirection level and loop.
+ */
+ if (level[level_i].blkcount == 0) {
+ if (++level_i == LEVELS)
+ break;
+ continue;
+ }
+
+ /* Get the next block at this level. */
+ blk = *(level[level_i].blknums++);
+ level[level_i].blkcount--;
+ if (params->fstype->needswap)
+ blk = bswap32(blk);
+
+#if 0
+ fprintf(stderr, "ino %lu blk %lu level %d\n", ino, blk,
+ level_i);
+#endif
+
+ /*
+ * If we're not at the direct level, descend one
+ * level, read in that level's new block list,
+ * and loop.
+ */
+ if (level_i > 0) {
+ level_i--;
+ if (blk == 0)
+ memset(level[level_i].diskbuf, 0, MAXBSIZE);
+ else if (! ffs_read_disk_block(params,
+ fsbtodb(fs, blk) + params->fstype->offset,
+ fs->fs_bsize, level[level_i].diskbuf))
+ return (0);
+ /* XXX ondisk32 */
+ level[level_i].blknums =
+ (int32_t *)level[level_i].diskbuf;
+ level[level_i].blkcount = NINDIR(fs);
+ continue;
+ }
+
+ /* blk is the next direct level block. */
+#if 0
+ fprintf(stderr, "ino %lu db %lu blksize %lu\n", ino,
+ fsbtodb(fs, blk), sblksize(fs, inode->di_size, lblk));
+#endif
+ rv = (*callback)(params, state,
+ fsbtodb(fs, blk) + params->fstype->offset,
+ sblksize(fs, (int64_t)inode->di_size, lblk));
+ lblk++;
+ nblk--;
+ if (rv != 1)
+ return (rv);
+ }
+
+ if (nblk != 0) {
+ warnx("Inode %llu in `%s' ran out of blocks?",
+ (unsigned long long)ino, params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+/*
+ * This iterates over the data blocks belonging to an inode,
+ * making a callback each iteration with the disk block number
+ * and the size.
+ */
+static int
+ffs_find_disk_blocks_ufs2(ib_params *params, ino_t ino,
+ int (*callback)(ib_params *, void *, uint64_t, uint32_t),
+ void *state)
+{
+ char sbbuf[SBLOCKSIZE];
+ struct fs *fs;
+ char inodebuf[MAXBSIZE];
+ struct ufs2_dinode *inode;
+ int level_i;
+ int64_t blk, lblk, nblk;
+ int rv;
+#define LEVELS 4
+ struct {
+ int64_t *blknums;
+ unsigned long blkcount;
+ char diskbuf[MAXBSIZE];
+ } level[LEVELS];
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+ assert(callback != NULL);
+ assert(state != NULL);
+
+ /* Read the superblock. */
+ if (!ffs_read_disk_block(params, params->fstype->sblockloc, SBLOCKSIZE,
+ sbbuf))
+ return (0);
+ fs = (struct fs *)sbbuf;
+#ifndef NO_FFS_SWAP
+ if (params->fstype->needswap)
+ ffs_sb_swap(fs, fs);
+#endif
+
+ if (fs->fs_inopb <= 0) {
+ warnx("Bad inopb %d in superblock in `%s'",
+ fs->fs_inopb, params->filesystem);
+ return (0);
+ }
+
+ /* Read the inode. */
+ if (! ffs_read_disk_block(params,
+ fsbtodb(fs, ino_to_fsba(fs, ino)) + params->fstype->offset,
+ fs->fs_bsize, inodebuf))
+ return (0);
+ inode = (struct ufs2_dinode *)inodebuf;
+ inode += ino_to_fsbo(fs, ino);
+#ifndef NO_FFS_SWAP
+ if (params->fstype->needswap)
+ ffs_dinode2_swap(inode, inode);
+#endif
+
+ /* Get the block count and initialize for our block walk. */
+ nblk = howmany(inode->di_size, fs->fs_bsize);
+ lblk = 0;
+ level_i = 0;
+ level[0].blknums = &inode->di_db[0];
+ level[0].blkcount = NDADDR;
+ level[1].blknums = &inode->di_ib[0];
+ level[1].blkcount = 1;
+ level[2].blknums = &inode->di_ib[1];
+ level[2].blkcount = 1;
+ level[3].blknums = &inode->di_ib[2];
+ level[3].blkcount = 1;
+
+ /* Walk the data blocks. */
+ while (nblk > 0) {
+
+ /*
+ * If there are no more blocks at this indirection
+ * level, move up one indirection level and loop.
+ */
+ if (level[level_i].blkcount == 0) {
+ if (++level_i == LEVELS)
+ break;
+ continue;
+ }
+
+ /* Get the next block at this level. */
+ blk = *(level[level_i].blknums++);
+ level[level_i].blkcount--;
+ if (params->fstype->needswap)
+ blk = bswap64(blk);
+
+#if 0
+ fprintf(stderr, "ino %lu blk %llu level %d\n", ino,
+ (unsigned long long)blk, level_i);
+#endif
+
+ /*
+ * If we're not at the direct level, descend one
+ * level, read in that level's new block list,
+ * and loop.
+ */
+ if (level_i > 0) {
+ level_i--;
+ if (blk == 0)
+ memset(level[level_i].diskbuf, 0, MAXBSIZE);
+ else if (! ffs_read_disk_block(params,
+ fsbtodb(fs, blk) + params->fstype->offset,
+ fs->fs_bsize, level[level_i].diskbuf))
+ return (0);
+ level[level_i].blknums =
+ (int64_t *)level[level_i].diskbuf;
+ level[level_i].blkcount = NINDIR(fs);
+ continue;
+ }
+
+ /* blk is the next direct level block. */
+#if 0
+ fprintf(stderr, "ino %lu db %llu blksize %lu\n", ino,
+ fsbtodb(fs, blk), sblksize(fs, inode->di_size, lblk));
+#endif
+ rv = (*callback)(params, state,
+ fsbtodb(fs, blk) + params->fstype->offset,
+ sblksize(fs, (int64_t)inode->di_size, lblk));
+ lblk++;
+ nblk--;
+ if (rv != 1)
+ return (rv);
+ }
+
+ if (nblk != 0) {
+ warnx("Inode %llu in `%s' ran out of blocks?",
+ (unsigned long long)ino, params->filesystem);
+ return (0);
+ }
+
+ return (1);
+}
+
+/*
+ * This callback reads a block of the root directory,
+ * searches for an entry for the secondary bootstrap,
+ * and saves the inode number if one is found.
+ */
+static int
+ffs_findstage2_ino(ib_params *params, void *_ino,
+ uint64_t blk, uint32_t blksize)
+{
+ char dirbuf[MAXBSIZE];
+ struct direct *de, *ede;
+ uint32_t ino;
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+ assert(params->stage2 != NULL);
+ assert(_ino != NULL);
+
+ /* Skip directory holes. */
+ if (blk == 0)
+ return (1);
+
+ /* Read the directory block. */
+ if (! ffs_read_disk_block(params, blk, blksize, dirbuf))
+ return (0);
+
+ /* Loop over the directory entries. */
+ de = (struct direct *)&dirbuf[0];
+ ede = (struct direct *)&dirbuf[blksize];
+ while (de < ede) {
+ ino = de->d_fileno;
+ if (params->fstype->needswap) {
+ ino = bswap32(ino);
+ de->d_reclen = bswap16(de->d_reclen);
+ }
+ if (ino != 0 && strcmp(de->d_name, params->stage2) == 0) {
+ *((uint32_t *)_ino) = ino;
+ return (2);
+ }
+ if (de->d_reclen == 0)
+ break;
+ de = (struct direct *)((char *)de + de->d_reclen);
+ }
+
+ return (1);
+}
+
+struct findblks_state {
+ uint32_t maxblk;
+ uint32_t nblk;
+ ib_block *blocks;
+};
+
+/* This callback records the blocks of the secondary bootstrap. */
+static int
+ffs_findstage2_blocks(ib_params *params, void *_state,
+ uint64_t blk, uint32_t blksize)
+{
+ struct findblks_state *state = _state;
+
+ assert(params != NULL);
+ assert(params->stage2 != NULL);
+ assert(_state != NULL);
+
+ if (state->nblk == state->maxblk) {
+ warnx("Secondary bootstrap `%s' has too many blocks (max %d)",
+ params->stage2, state->maxblk);
+ return (0);
+ }
+ state->blocks[state->nblk].block = blk;
+ state->blocks[state->nblk].blocksize = blksize;
+ state->nblk++;
+ return (1);
+}
+
+/*
+ * publicly visible functions
+ */
+
+static off_t sblock_try[] = SBLOCKSEARCH;
+
+int
+ffs_match(ib_params *params)
+{
+ return ffs_match_common(params, (off_t) 0);
+}
+
+int
+raid_match(ib_params *params)
+{
+ /* XXX Assumes 512 bytes / sector */
+ if (params->sectorsize != 512) {
+ warnx("Media is %d bytes/sector."
+ " RAID is only supported on 512 bytes/sector media.",
+ params->sectorsize);
+ return 0;
+ }
+ return ffs_match_common(params, (off_t) RF_PROTECTED_SECTORS);
+}
+
+int
+ffs_match_common(ib_params *params, off_t offset)
+{
+ char sbbuf[SBLOCKSIZE];
+ struct fs *fs;
+ int i;
+ off_t loc;
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+
+ fs = (struct fs *)sbbuf;
+ for (i = 0; sblock_try[i] != -1; i++) {
+ loc = sblock_try[i] / params->sectorsize + offset;
+ if (!ffs_read_disk_block(params, loc, SBLOCKSIZE, sbbuf))
+ continue;
+ switch (fs->fs_magic) {
+ case FS_UFS2_MAGIC:
+ is_ufs2 = 1;
+ /* FALLTHROUGH */
+ case FS_UFS1_MAGIC:
+ params->fstype->needswap = 0;
+ params->fstype->blocksize = fs->fs_bsize;
+ params->fstype->sblockloc = loc;
+ params->fstype->offset = offset;
+ break;
+#ifndef FFS_NO_SWAP
+ case FS_UFS2_MAGIC_SWAPPED:
+ is_ufs2 = 1;
+ /* FALLTHROUGH */
+ case FS_UFS1_MAGIC_SWAPPED:
+ params->fstype->needswap = 1;
+ params->fstype->blocksize = bswap32(fs->fs_bsize);
+ params->fstype->sblockloc = loc;
+ params->fstype->offset = offset;
+ break;
+#endif
+ default:
+ continue;
+ }
+ if (!is_ufs2 && sblock_try[i] == SBLOCK_UFS2)
+ continue;
+ return 1;
+ }
+
+ return (0);
+}
+
+int
+ffs_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
+{
+ int rv;
+ uint32_t ino;
+ struct findblks_state state;
+
+ assert(params != NULL);
+ assert(params->stage2 != NULL);
+ assert(maxblk != NULL);
+ assert(blocks != NULL);
+
+ if (params->flags & IB_STAGE2START)
+ return (hardcode_stage2(params, maxblk, blocks));
+
+ /* The secondary bootstrap must be clearly in /. */
+ if (params->stage2[0] == '/')
+ params->stage2++;
+ if (strchr(params->stage2, '/') != NULL) {
+ warnx("The secondary bootstrap `%s' must be in /",
+ params->stage2);
+ warnx("(Path must be relative to the file system in `%s')",
+ params->filesystem);
+ return (0);
+ }
+
+ /* Get the inode number of the secondary bootstrap. */
+ if (is_ufs2)
+ rv = ffs_find_disk_blocks_ufs2(params, ROOTINO,
+ ffs_findstage2_ino, &ino);
+ else
+ rv = ffs_find_disk_blocks_ufs1(params, ROOTINO,
+ ffs_findstage2_ino, &ino);
+ if (rv != 2) {
+ warnx("Could not find secondary bootstrap `%s' in `%s'",
+ params->stage2, params->filesystem);
+ warnx("(Path must be relative to the file system in `%s')",
+ params->filesystem);
+ return (0);
+ }
+
+ /* Record the disk blocks of the secondary bootstrap. */
+ state.maxblk = *maxblk;
+ state.nblk = 0;
+ state.blocks = blocks;
+ if (is_ufs2)
+ rv = ffs_find_disk_blocks_ufs2(params, ino,
+ ffs_findstage2_blocks, &state);
+ else
+ rv = ffs_find_disk_blocks_ufs1(params, ino,
+ ffs_findstage2_blocks, &state);
+ if (! rv) {
+ return (0);
+ }
+
+ *maxblk = state.nblk;
+ return (1);
+}
--- /dev/null
+/* $NetBSD: fstypes.c,v 1.13 2010/01/14 16:27:49 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette and Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: fstypes.c,v 1.13 2010/01/14 16:27:49 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+
+#include "installboot.h"
+
+struct ib_fs fstypes[] = {
+#ifndef NO_STAGE2
+ { .name = "ffs", .match = ffs_match, .findstage2 = ffs_findstage2 },
+ { .name = "raid", .match = raid_match, .findstage2 = ffs_findstage2 },
+ { .name = "raw", .match = raw_match, .findstage2 = raw_findstage2 },
+#endif
+ { .name = NULL, }
+};
+
+#ifndef NO_STAGE2
+int
+hardcode_stage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
+{
+ struct stat s2sb;
+ uint32_t nblk, i;
+
+ assert(params != NULL);
+ assert(params->stage2 != NULL);
+ assert(maxblk != NULL);
+ assert(blocks != NULL);
+ assert((params->flags & IB_STAGE2START) != 0);
+ assert(params->fstype != NULL);
+ assert(params->fstype->blocksize != 0);
+
+ if (stat(params->stage2, &s2sb) == -1) {
+ warn("Examining `%s'", params->stage2);
+ return (0);
+ }
+ if (!S_ISREG(s2sb.st_mode)) {
+ warnx("`%s' must be a regular file", params->stage2);
+ return (0);
+ }
+
+ nblk = s2sb.st_size / params->fstype->blocksize;
+ if (s2sb.st_size % params->fstype->blocksize != 0)
+ nblk++;
+#if 0
+ fprintf(stderr, "for %s got size %lld blksize %u blocks %u\n",
+ params->stage2, s2sb.st_size, params->fstype->blocksize, nblk);
+#endif
+ if (nblk > *maxblk) {
+ warnx("Secondary bootstrap `%s' has too many blocks "
+ "(calculated %u, maximum %u)",
+ params->stage2, nblk, *maxblk);
+ return (0);
+ }
+
+ for (i = 0; i < nblk; i++) {
+ blocks[i].block = params->s2start +
+ i * (params->fstype->blocksize / params->sectorsize);
+ blocks[i].blocksize = params->fstype->blocksize;
+ }
+ *maxblk = nblk;
+
+ return (1);
+}
+
+
+int
+raw_match(ib_params *params)
+{
+
+ assert(params != NULL);
+ assert(params->fstype != NULL);
+
+ params->fstype->blocksize = 8192; // XXX: hardcode
+ return (1); /* can always write to a "raw" file system */
+}
+
+int
+raw_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
+{
+
+ assert(params != NULL);
+ assert(params->stage2 != NULL);
+ assert(maxblk != NULL);
+ assert(blocks != NULL);
+
+ if ((params->flags & IB_STAGE2START) == 0) {
+ warnx("Need `-B bno' for raw file systems");
+ return (0);
+ }
+ return (hardcode_stage2(params, maxblk, blocks));
+}
+#endif
--- /dev/null
+.\" $NetBSD: installboot.8,v 1.79 2011/11/03 20:09:18 martin Exp $
+.\"
+.\" Copyright (c) 2002-2009 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Luke Mewburn of Wasabi Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd August 3, 2011
+.Dt INSTALLBOOT 8
+.Os
+.Sh NAME
+.Nm installboot
+.Nd install disk bootstrap software
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl fnv
+.Op Fl B Ar s2bno
+.Op Fl b Ar s1bno
+.Op Fl m Ar machine
+.Op Fl o Ar options
+.Op Fl t Ar fstype
+.Ar filesystem
+.Ar primary
+.Op Ar secondary
+.Nm
+.Fl c
+.Op Fl fnv
+.Op Fl m Ar machine
+.Op Fl o Ar options
+.Op Fl t Ar fstype
+.Ar filesystem
+.Nm
+.Fl e
+.Op Fl fnv
+.Op Fl m Ar machine
+.Op Fl o Ar options
+.Ar bootstrap
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility installs and removes
+.Nx
+disk bootstrap software into a file system.
+.Nm
+can install
+.Ar primary
+into
+.Ar filesystem ,
+or disable an existing bootstrap in
+.Ar filesystem .
+.Pp
+On some architectures the options of an existing installed bootstrap,
+or those of a bootstrap file can be changed.
+Installing a new primary bootstrap will reset those options to default
+values.
+.Pp
+Generally,
+.Nx
+disk bootstrap software consists of two parts: a
+.Dq primary
+bootstrap program usually written into the disklabel area of the
+file system by
+.Nm ,
+and a
+.Dq secondary
+bootstrap program that usually resides as an ordinary file in the file system.
+.Pp
+When booting, the primary bootstrap program is loaded and invoked by
+the machine's PROM or BIOS.
+After receiving control of the system it loads and runs the secondary
+bootstrap program, which in turn loads and runs the kernel.
+The secondary bootstrap may allow control over various boot parameters
+passed to the kernel.
+.Pp
+Perform the following steps to make a file system bootable:
+.Bl -enum
+.It
+Copy the secondary bootstrap (usually
+.Pa /usr/mdec/boot. Ns Sy MACHINE
+or
+.Pa /usr/mdec/boot )
+to the root directory of the target file system.
+.Pp
+.
+.It
+Use
+.Nm
+to install the primary bootstrap program
+(usually
+.Pa /usr/mdec/bootxx_ Ns Sy FSTYPE )
+into
+.Ar filesystem .
+.Pp
+The following platforms do not require this step if the primary bootstrap
+already exists and the secondary bootstrap file is just being updated:
+.Sy alpha ,
+.Sy amd64 ,
+.Sy amiga ,
+.Sy i386 ,
+.Sy pmax ,
+.Sy sparc64 ,
+and
+.Sy vax .
+.Pp
+The following platform does not require the first step since a
+single bootstrap file is used.
+The single bootstrap is installed like the primary bootstrap on
+other platforms:
+.Sy next68k .
+.Pp
+.El
+.Pp
+The options and arguments recognized by
+.Nm
+are as follows:
+.
+.Bl -tag -width "optionsxxx"
+.
+.It Fl B Ar s2bno
+When hard-coding the blocks of
+.Ar secondary
+into
+.Ar primary ,
+start from block
+.Ar s2bno
+instead of trying to determine the block numbers occupied by
+.Ar secondary
+by examining
+.Ar filesystem .
+If this option is supplied,
+.Ar secondary
+should refer to an actual secondary bootstrap (rather than the
+file name of the one present in
+.Ar filesystem )
+so that its size can be determined.
+.
+.It Fl b Ar s1bno
+Install
+.Ar primary
+at block number
+.Ar s1bno
+instead of the default location for the machine and file system type.
+.Sy [ alpha ,
+.Sy pmax ,
+.Sy vax ]
+.
+.It Fl c
+Clear (remove) any existing bootstrap instead of installing one.
+.
+.It Fl e
+Edit the options of an existing bootstrap.
+This can be use to change the options in bootxx_xxxfs files,
+raw disk partitions, and the
+.Pa pxeboot_ia32.bin
+file.
+With
+.Fl v
+and without
+.Fl o ,
+show the current options.
+.Sy [ amd64 , i386 ]
+.
+.It Fl f
+Forces
+.Nm
+to ignore some errors.
+.
+.It Fl m Ar machine
+Use
+.Ar machine
+as the target machine type.
+The default machine is determined from
+.Xr uname 3
+and then
+.Ev MACHINE .
+The following machines are currently supported by
+.Nm :
+.Bd -ragged -offset indent
+.Sy alpha ,
+.Sy amd64 ,
+.Sy amiga ,
+.Sy ews4800mips ,
+.Sy hp300 ,
+.Sy hp700 ,
+.Sy i386 ,
+.Sy landisk ,
+.Sy macppc ,
+.Sy news68k ,
+.Sy newsmips ,
+.Sy next68k ,
+.Sy pmax ,
+.Sy sparc ,
+.Sy sparc64 ,
+.Sy sun2 ,
+.Sy sun3 ,
+.Sy vax ,
+.Sy x68k
+.Ed
+.
+.
+.It Fl n
+Do not write to
+.Ar filesystem .
+.
+.It Fl o Ar options
+Machine specific
+.Nm
+options, comma separated.
+.Pp
+Supported options are (with the machines for they are valid in brackets):
+.
+.Bl -tag -offset indent -width alphasum
+.
+.It Sy alphasum
+.Sy [ alpha ]
+Recalculate and restore the Alpha checksum.
+This is the default for
+.Nx Ns Tn /alpha .
+.
+.It Sy append
+.Sy [ alpha ,
+.Sy pmax ,
+.Sy vax ]
+Append
+.Ar primary
+to the end of
+.Ar filesystem ,
+which must be a regular file in this case.
+.
+.It Sy bootconf
+.Sy [ amd64 ,
+.Sy i386 ]
+(Don't) read a
+.Dq boot.cfg
+file.
+.
+.It Sy command=\*[Lt]boot command\*[Gt]
+.Sy [ amiga ]
+Modify the default boot command line.
+.
+.It Sy console=\*[Lt]console name\*[Gt]
+.Sy [ amd64 ,
+.Sy i386 ]
+Set the console device, \*[Lt]console name\*[Gt] must be one of:
+pc, com0, com1, com2, com3, com0kbd, com1kbd, com2kbd or com3kbd.
+.
+.It Sy ioaddr=\*[Lt]ioaddr\*[Gt]
+.Sy [ amd64 ,
+.Sy i386 ]
+Set the IO address to be used for the console serial port.
+Defaults to the IO address used by the system BIOS for the specified port.
+.
+.It Sy keymap=\*[Lt]keymap\*[Gt]
+.Sy [ amd64 ,
+.Sy i386 ]
+Set a boot time keyboard translation map.
+Each character in \*[Lt]keymap\*[Gt] will be replaced by the one following it.
+For example, an argument of
+.Dq zyz
+would swap the lowercase letters
+.Sq y
+and
+.Sq z .
+.
+.It Sy modules
+.Sy [ amd64 ,
+.Sy i386 ]
+(Don't) load kernel modules.
+.
+.It Sy password=\*[Lt]password\*[Gt]
+.Sy [ amd64 ,
+.Sy i386 ]
+Set the password which must be entered before the boot menu can be accessed.
+.
+.It Sy resetvideo
+.Sy [ amd64 ,
+.Sy i386 ]
+Reset the video before booting.
+.
+.It Sy speed=\*[Lt]baud rate\*[Gt]
+.Sy [ amd64 ,
+.Sy i386 ]
+Set the baud rate for the serial console.
+If a value of zero is specified, then the current baud rate (set by the
+BIOS) will be used.
+.
+.It Sy sunsum
+.Sy [ alpha ,
+.Sy pmax ,
+.Sy vax ]
+Recalculate and restore the Sun and
+.Nx Ns Tn /sparc
+compatible checksum.
+.Em Note :
+The existing
+.Nx Ns Tn /sparc
+disklabel should use no more than 4 partitions.
+.
+.It Sy timeout=\*[Lt]seconds\*[Gt]
+.Sy [ amd64 ,
+.Sy i386 ]
+Set the timeout before the automatic boot begins to the given number of seconds.
+.El
+.
+.It Fl t Ar fstype
+Use
+.Ar fstype
+as the type of
+.Ar filesystem .
+The default operation is to attempt to auto-detect this setting.
+The following file system types are currently supported by
+.Nm :
+.
+.Bl -tag -offset indent -width raid
+.
+.It Sy ffs
+.Bx
+Fast File System.
+.
+.It Sy raid
+Mirrored RAIDframe File System.
+.
+.It Sy raw
+.Sq Raw
+image.
+Note: if a platform needs to hard-code the block offset of the secondary
+bootstrap, it cannot be searched for on this file system type, and must
+be provided with
+.Fl B Ar s2bno .
+.El
+.
+.It Fl v
+Verbose operation.
+.
+.It Ar filesystem
+The path name of the device or file system image that
+.Nm
+is to operate on.
+It is not necessary for
+.Ar filesystem
+to be a currently mounted file system.
+.
+.It Ar primary
+The path name of the
+.Dq primary
+boot block to install.
+The path name must refer to a file in a file system that is currently
+mounted.
+.
+.It Ar secondary
+The path name of the
+.Dq secondary
+boot block, relative to the root of
+the file system in the device or image specified by the
+.Ar filesystem
+argument.
+Note that this may refer to a file in a file system that is not mounted.
+Most systems require
+.Ar secondary
+to be in the
+.Dq root
+directory of the file system, so the leading
+.Dq Pa /
+is not necessary on
+.Ar secondary .
+.Pp
+Only certain combinations of
+platform
+.Pq Fl m Ar machine
+and file system type
+.Pq Fl t Ar fstype
+require that the name of the secondary bootstrap is
+supplied as
+.Ar secondary ,
+so that information such as the disk block numbers occupied
+by the secondary bootstrap can be stored in the primary bootstrap.
+These are:
+.Bl -column "Platform" "File systems" -offset indent
+.It Sy "Platform" Ta Sy "File systems"
+.It macppc Ta ffs, raw
+.It news68k Ta ffs, raw
+.It newsmips Ta ffs, raw
+.It sparc Ta ffs, raid, raw
+.It sun2 Ta ffs, raw
+.It sun3 Ta ffs, raw
+.El
+.El
+.Pp
+.Nm
+exits 0 on success, and \*[Gt]0 if an error occurs.
+.
+.Sh ENVIRONMENT
+.Nm
+uses the following environment variables:
+.
+.Bl -tag -width "MACHINE"
+.
+.It Ev MACHINE
+Default value for
+.Ar machine ,
+overriding the result from
+.Xr uname 3 .
+.
+.El
+.
+.Sh FILES
+Most
+.Nx
+ports will contain variations of the following files:
+.Pp
+.Bl -tag -width /usr/mdec/bootxx_ustarfs
+.
+.It Pa /usr/mdec/bootxx_ Ns Sy FSTYPE
+Primary bootstrap for file system type
+.Sy FSTYPE .
+Installed into the bootstrap area of the file system by
+.Nm .
+.
+.It Pa /usr/mdec/bootxx_fat16
+Primary bootstrap for
+.Tn MS-DOS
+.Sy FAT16
+file systems.
+This differs from
+.Nm bootxx_msdos
+in that it doesn't require the filesystem to have been initialised with
+any
+.Ql reserved sectors .
+It also uses the information in the
+.Ql Boot Parameter Block
+to get the media and filesytem properties.
+.
+.It Pa /usr/mdec/bootxx_ffsv1
+Primary bootstrap for
+.Sy FFSv1
+file systems
+(the "traditional"
+.Nx
+file system).
+Use
+.Xr dumpfs 8
+to confirm the file system format is
+.Sy FFSv1 .
+.
+.It Pa /usr/mdec/bootxx_ffsv2
+Primary bootstrap for
+.Sy FFSv2
+file systems.
+Use
+.Xr dumpfs 8
+to confirm the file system format is
+.Sy FFSv2 .
+.
+.It Pa /usr/mdec/bootxx_lfsv1
+Primary bootstrap for
+.Sy LFSv1
+file systems.
+.
+.It Pa /usr/mdec/bootxx_lfsv2
+Primary bootstrap for
+.Sy LFSv2
+file systems
+(the default LFS version).
+.
+.It Pa /usr/mdec/bootxx_msdos
+Primary bootstrap for
+.Tn MS-DOS
+.Sy FAT
+file systems.
+.
+.It Pa /usr/mdec/bootxx_ustarfs
+Primary bootstrap for
+.Sy TARFS
+boot images.
+This is used by various install media.
+.
+.It Pa /usr/mdec/boot. Ns Sy MACHINE
+Secondary bootstrap for machine type
+.Sy MACHINE .
+This should be installed into the file system before
+.Nm
+is run.
+.
+.It Pa /usr/mdec/boot
+Synonym for
+.Pa /usr/mdec/boot. Ns Sy MACHINE
+.
+.It Pa /boot. Ns Sy MACHINE
+Installed copy of secondary bootstrap for machine type
+.Sy MACHINE .
+.
+.It Pa /boot
+Installed copy of secondary bootstrap.
+Searched for by the primary bootstrap if
+.Pa /boot. Ns Sy MACHINE
+is not found.
+.
+.El
+.
+.Ss Nx Ns Tn /macppc files
+.
+.Bl -tag -width /usr/mdec/bootxx_ustarfs
+.
+.It Pa /usr/mdec/bootxx
+.Nx Ns Tn /macppc
+primary bootstrap.
+.
+.It Pa /usr/mdec/ofwboot
+.Nx Ns Tn /macppc
+secondary bootstrap.
+.
+.It Pa /ofwboot
+Installed copy of
+.Nx Ns Tn /macppc
+secondary bootstrap.
+.
+.El
+.
+.Ss Nx Ns Tn /next68k files
+.
+.Bl -tag -width /usr/mdec/bootxx_ustarfs
+.
+.It Pa /usr/mdec/boot
+.Nx Ns Tn /next68k
+bootstrap.
+.
+.El
+.
+.Ss Nx Ns Tn /sparc64 files
+.
+.Bl -tag -width /usr/mdec/bootxx_ustarfs
+.
+.It Pa /usr/mdec/bootblk
+.Nx Ns Tn /sparc64
+primary bootstrap.
+.
+.It Pa /usr/mdec/ofwboot
+.Nx Ns Tn /sparc64
+secondary bootstrap.
+.
+.It Pa /ofwboot
+Installed copy of
+.Nx Ns Tn /sparc64
+secondary bootstrap.
+.
+.El
+.
+.Sh EXAMPLES
+.
+.Ss common
+Verbosely install the Berkeley Fast File System primary bootstrap on to disk
+.Sq sd0 :
+.Dl Ic installboot -v /dev/rsd0c /usr/mdec/bootxx_ffs
+Note: the
+.Dq whole disk
+partition (c on some ports, d on others) is used here, since the a partition
+probably is already opened (mounted as
+.Pa / ) ,
+so
+.Nm
+would not be able to access it.
+.Pp
+Remove the primary bootstrap from disk
+.Sq sd1 :
+.Dl Ic installboot -c /dev/rsd1c
+.
+.Ss Nx Ns Tn /amiga
+Modify the command line to change the default from "netbsd -ASn2" to
+"netbsd -S":
+.Dl Ic installboot -m amiga -o command="netbsd -S" /dev/rsd0a /usr/mdec/bootxx_ffs
+.
+.Ss Nx Ns Tn /ews4800mips
+Install the System V Boot File System primary bootstrap on to disk
+.Sq sd0 ,
+with the secondary bootstrap
+.Sq Pa /boot
+already present in the SysVBFS partition on the disk:
+.Dl Ic installboot /dev/rsd0c /usr/mdec/bootxx_bfs
+.
+.Ss Nx Ns Tn /i386 and Nx Ns Tn /amd64
+Install new boot blocks on an existing mounted root file system on
+.Sq wd0 ,
+setting the timeout to five seconds, after copying a new secondary
+bootstrap:
+.Dl Ic cp /usr/mdec/boot /boot
+.Dl Ic installboot -v -o timeout=5 /dev/rwd0a /usr/mdec/bootxx_ffsv1
+.
+.Pp
+Create a bootable CD-ROM with an ISO9660
+file system for an i386 system with a serial console:
+.Dl Ic mkdir cdrom
+.Dl Ic cp sys/arch/i386/compile/mykernel/netbsd cdrom/netbsd
+.Dl Ic cp /usr/mdec/boot cdrom/boot
+.Dl Ic cp /usr/mdec/bootxx_cd9660 bootxx
+.Dl Ic installboot -o console=com0,speed=19200 -m i386 -e bootxx
+.Dl Ic makefs -t cd9660 -o 'bootimage=i386;bootxx,no-emul-boot' boot.iso \
+ cdrom
+.
+.Pp
+Create a bootable floppy disk with an FFSv1
+file system for a small custom kernel (note: bigger kernels needing
+multiple disks are handled with the ustarfs file system):
+.Dl Ic newfs -s 1440k /dev/rfd0a
+.Bd -ragged -offset indent-two -compact
+.Em Note :
+Ignore the warnings that
+.Xr newfs 8
+displays; it can not write a disklabel,
+which is not a problem for a floppy disk.
+.Ed
+.Dl Ic mount /dev/fd0a /mnt
+.Dl Ic cp /usr/mdec/boot /mnt/boot
+.Dl Ic gzip -9 \*[Lt] sys/arch/i386/compile/mykernel/netbsd \*[Gt] /mnt/netbsd.gz
+.Dl Ic umount /mnt
+.Dl Ic installboot -v /dev/rfd0a /usr/mdec/bootxx_ffsv1
+.
+.Pp
+Create a bootable FAT file system on
+.Sq wd1a ,
+which should have the same offset and size as a FAT primary partition
+in the Master Boot Record (MBR):
+.Dl Ic newfs_msdos -r 16 /dev/rwd1a
+.Bd -ragged -offset indent-two -compact
+.Em Notes :
+The
+.Fl r Ar 16
+is to reserve space for the primary bootstrap.
+.Xr newfs_msdos 8
+will display an
+.Dq MBR type
+such as
+.Ql 1 ,
+.Ql 4 ,
+or
+.Ql 6 ;
+the MBR partition type of the appropriate primary partition should be
+changed to this value.
+.Ed
+.Dl Ic mount -t msdos /dev/wd1a /mnt
+.Dl Ic cp /usr/mdec/boot /mnt/boot
+.Dl Ic cp path/to/kernel /mnt/netbsd
+.Dl Ic umount /mnt
+.Dl Ic installboot -t raw /dev/rwd1a /usr/mdec/bootxx_msdos
+.Pp
+Make the existing FAT16 filesystem on
+.Sq sd0e
+bootable.
+This can be used to make USB memory bootable provided it has 512 byte
+sectors and that the manufacturer correctly initialised the file system.
+.Dl Ic mount -t msdos /dev/sd0e /mnt
+.Dl Ic cp /usr/mdec/boot /mnt/boot
+.Dl Ic cp path/to/kernel /mnt/netbsd
+.Dl Ic umount /mnt
+.Dl Ic installboot /dev/rsd0e /usr/mdec/bootxx_fat16
+It may also be necessary to use
+.Nm fdisk
+to make the device itself bootable.
+.
+.Pp
+Switch the existing installed bootstrap to use a serial console without
+reinstalling or altering other options such as timeout.
+.Dl Ic installboot -e -o console=com0 /dev/rwd0a
+.Ss Nx Ns Tn /macppc
+Note the
+.Nm
+utility is only required for macppc machines with OpenFirmware version 2
+to boot.
+OpenFirmware 3 cannot load bootblocks specified in the Apple partition
+map.
+.Pp
+Install the Berkeley Fast File System primary bootstrap on to disk
+.Sq wd0 :
+.Dl Ic installboot /dev/rwd0c /usr/mdec/bootxx /ofwboot
+.Pp
+The secondary
+.Nx Ns Tn /macppc
+bootstrap is located in
+.Pa /usr/mdec/ofwboot .
+.Pp
+The primary bootstrap requires the raw
+.Pa ofwboot
+for the secondary bootstrap, not
+.Pa ofwboot.xcf ,
+which is used for the OpenFirmware to load kernels.
+.Ss Nx Ns Tn /next68k
+Install the bootstrap on to disk
+.Sq sd0 :
+.Dl Ic installboot /dev/rsd0c /usr/mdec/boot
+.Pp
+.
+.Ss Nx Ns Tn /pmax
+Install the Berkeley Fast File System primary bootstrap on to disk
+.Sq sd0 :
+.Dl Ic installboot /dev/rsd0c /usr/mdec/bootxx_ffs
+.Pp
+.Nx Ns Tn /pmax
+requires that this file system starts at block 0 of the disk.
+.Pp
+Install the ISO 9660 primary bootstrap in the file
+.Pa /tmp/cd-image :
+.Dl Ic installboot -m pmax /tmp/cd-image /usr/mdec/bootxx_cd9660
+.Pp
+Make an ISO 9660 filesystem in the file
+.Pa /tmp/cd-image
+and install the ISO 9660 primary bootstrap in the filesystem, where the
+source directory for the ISO 9660 filesystem contains a kernel, the
+primary bootstrap
+.Pa bootxx_cd9660
+and the secondary bootstrap
+.Pa boot.pmax :
+.Dl Ic mkisofs -o /tmp/cd-image -a -l -v iso-source-dir
+.Dl ...
+.Dl 48 51 iso-source-dir/bootxx_cd9660
+.Dl ...
+.Dl Ic installboot -b `expr 48 \e* 4` /tmp/cd-image /usr/mdec/bootxx_cd9660
+.
+.Ss Nx Ns Tn /sparc
+Install the Berkeley Fast File System primary bootstrap on to disk
+.Sq sd0 ,
+with the secondary bootstrap
+.Sq Pa /boot
+already present:
+.Dl Ic installboot /dev/rsd0c /usr/mdec/bootxx /boot
+.
+.Ss Nx Ns Tn /sparc64
+Install the primary bootstrap on to disk
+.Sq sd0 :
+.Dl Ic installboot /dev/rsd0c /usr/mdec/bootblk
+.Pp
+The secondary
+.Nx Ns Tn /sparc64
+bootstrap is located in
+.Pa /usr/mdec/ofwboot .
+.
+.Ss Nx Ns Tn /sun2 and Nx Ns Tn /sun3
+Install the Berkeley Fast File System primary bootstrap on to disk
+.Sq sd0 ,
+with the secondary bootstrap
+.Sq Pa /boot
+already present:
+.Dl Ic installboot /dev/rsd0c /usr/mdec/bootxx /boot
+.
+.Sh SEE ALSO
+.Xr uname 3 ,
+.Xr boot 8 ,
+.Xr disklabel 8 ,
+.Xr dumpfs 8 ,
+.Xr fdisk 8 ,
+.Xr pxeboot 8
+.
+.Sh HISTORY
+This implementation of
+.Nm
+appeared in
+.Nx 1.6 .
+.
+.Sh AUTHORS
+The machine independent portion of this implementation of
+.Nm
+was written by Luke Mewburn.
+The following people contributed to the various machine dependent
+back-ends:
+Simon Burge (pmax),
+Chris Demetriou (alpha),
+Matthew Fredette (sun2, sun3),
+Matthew Green (sparc64),
+Ross Harvey (alpha),
+Michael Hitch (amiga),
+Paul Kranenburg (sparc),
+David Laight (i386),
+Christian Limpach (next68k),
+Luke Mewburn (macppc),
+Matt Thomas (vax),
+Izumi Tsutsui (news68k, newsmips),
+and
+UCHIYAMA Yasushi (ews4800mips).
+.
+.Sh BUGS
+There are not currently primary bootstraps to support all file systems
+types which are capable of being the root file system.
+.Pp
+If a disk has been converted from
+.Sy FFS
+to
+.Sy RAID
+without the contents of the disk erased, then the original
+.Sy FFS
+installation may be auto-detected instead of the
+.Sy RAID
+installation.
+In this case, the
+.Fl t Ar raid
+option must be provided.
+.
+.Ss Nx Ns Tn /alpha
+The
+.Nx Ns Tn /alpha
+primary bootstrap program can only load the secondary bootstrap program
+from file systems starting at the beginning (block 0) of disks.
+Similarly, the secondary bootstrap program can only load kernels from
+file systems starting at the beginning of disks.
+.Pp
+The size of primary bootstrap programs is restricted to 7.5KB, even
+though some file systems (e.g., ISO 9660) are able to accommodate larger
+ones.
+.
+.Ss Nx Ns Tn /hp300
+The disk must have a boot partition large enough to hold the bootstrap code.
+Currently the primary bootstrap must be a LIF format file.
+.
+.Ss Nx Ns Tn /i386 and Nx Ns Tn /amd64
+The bootstrap must be installed in the
+.Nx
+partition that starts at the beginning of the mbr partition.
+If that is a valid filesystem and contains the
+.Pa /boot
+program then it will be used as the root filesystem, otherwise the
+.Sq a
+partition will be booted.
+.Pp
+The size of primary bootstrap programs is restricted to 8KB, even
+though some file systems (e.g., ISO 9660) are able to accommodate larger
+ones.
+.
+.Ss Nx Ns Tn /macppc
+Due to restrictions in
+.Nm
+and the secondary bootstrap implementation, file systems where kernels exist
+must start at the beginning of disks.
+.Pp
+Currently,
+.Nm
+doesn't recognize an existing Apple partition map on the disk
+and always writes a faked map to make disks bootable.
+.Pp
+The
+.Nx Ns Tn /macppc
+bootstrap program can't load kernels from
+.Sy FFSv2
+partitions.
+.Ss Nx Ns Tn /next68k
+The size of bootstrap programs is restricted to the free space before
+the file system at the beginning of the disk minus 8KB.
+.
+.Ss Nx Ns Tn /pmax
+The
+.Nx Ns Tn /pmax
+secondary bootstrap program can only load kernels from file
+systems starting at the beginning of disks.
+.Pp
+The size of primary bootstrap programs is restricted to 7.5KB, even
+though some file systems (e.g., ISO 9660) are able to accommodate larger
+ones.
+.
+.Ss Nx Ns Tn /sun2 and Nx Ns Tn /sun3
+The
+.Nx Ns Tn /sun2
+and
+.Nx Ns Tn /sun3
+secondary bootstrap program can only load kernels from file
+systems starting at the beginning of disks.
+.
+.Ss Nx Ns Tn /vax
+The
+.Nx Ns Tn /vax
+secondary bootstrap program can only load kernels from file systems
+starting at the beginning of disks.
+.Pp
+The size of primary bootstrap programs is restricted to 7.5KB, even
+though some file systems (e.g., ISO 9660) are able to accommodate larger
+ones.
--- /dev/null
+/* $NetBSD: installboot.c,v 1.36 2011/11/03 20:46:41 martin Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: installboot.c,v 1.36 2011/11/03 20:46:41 martin Exp $");
+#endif /* !__lint */
+
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "installboot.h"
+
+static void getmachine(ib_params *, const char *, const char *);
+static void getfstype(ib_params *, const char *, const char *);
+static void parseoptions(ib_params *, const char *);
+__dead static void usage(void);
+static void options_usage(void);
+static void machine_usage(void);
+static void fstype_usage(void);
+
+static ib_params installboot_params;
+
+#define OFFSET(field) offsetof(ib_params, field)
+const struct option {
+ const char *name; /* Name of option */
+ ib_flags flag; /* Corresponding IB_xxx flag */
+ enum { /* Type of option value... */
+ OPT_BOOL, /* no value */
+ OPT_INT, /* numeric value */
+ OPT_WORD, /* space/tab/, terminated */
+ OPT_STRING /* null terminated */
+ } type;
+ int offset; /* of field in ib_params */
+} options[] = {
+ { "alphasum", IB_ALPHASUM, OPT_BOOL, 0 },
+ { "append", IB_APPEND, OPT_BOOL, 0 },
+ { "command", IB_COMMAND, OPT_STRING, OFFSET(command) },
+ { "console", IB_CONSOLE, OPT_WORD, OFFSET(console) },
+ { "ioaddr", IB_CONSADDR, OPT_INT, OFFSET(consaddr) },
+ { "keymap", IB_KEYMAP, OPT_WORD, OFFSET(keymap) },
+ { "password", IB_PASSWORD, OPT_WORD, OFFSET(password) },
+ { "resetvideo", IB_RESETVIDEO, OPT_BOOL, 0 },
+ { "speed", IB_CONSPEED, OPT_INT, OFFSET(conspeed) },
+ { "sunsum", IB_SUNSUM, OPT_BOOL, 0 },
+ { "timeout", IB_TIMEOUT, OPT_INT, OFFSET(timeout) },
+ { "modules", IB_MODULES, OPT_BOOL, 0 },
+ { "bootconf", IB_BOOTCONF, OPT_BOOL, 0 },
+ { .name = NULL },
+};
+#undef OFFSET
+#define OPTION(params, type, opt) (*(type *)((char *)(params) + (opt)->offset))
+
+#define DFL_SECSIZE 512 /* Don't use DEV_BSIZE. It's host's value. */
+
+int
+main(int argc, char *argv[])
+{
+ struct utsname utsname;
+ ib_params *params;
+ unsigned long lval;
+ int ch, rv, mode;
+ char *p;
+ const char *op;
+ ib_flags unsupported_flags;
+
+ setprogname(argv[0]);
+ params = &installboot_params;
+ memset(params, 0, sizeof(*params));
+ params->fsfd = -1;
+ params->s1fd = -1;
+ if ((p = getenv("MACHINE")) != NULL)
+ getmachine(params, p, "$MACHINE");
+
+ while ((ch = getopt(argc, argv, "b:B:cefm:no:t:v")) != -1) {
+ switch (ch) {
+
+ case 'b':
+ case 'B':
+ if (*optarg == '\0')
+ goto badblock;
+ lval = strtoul(optarg, &p, 0);
+ if (lval > UINT32_MAX || *p != '\0') {
+ badblock:
+ errx(1, "Invalid block number `%s'", optarg);
+ }
+ if (ch == 'b') {
+ params->s1start = (uint32_t)lval;
+ params->flags |= IB_STAGE1START;
+ } else {
+ params->s2start = (uint32_t)lval;
+ params->flags |= IB_STAGE2START;
+ }
+ break;
+
+ case 'c':
+ params->flags |= IB_CLEAR;
+ break;
+
+ case 'e':
+ params->flags |= IB_EDIT;
+ break;
+
+ case 'f':
+ params->flags |= IB_FORCE;
+ break;
+
+ case 'm':
+ getmachine(params, optarg, "-m");
+ break;
+
+ case 'n':
+ params->flags |= IB_NOWRITE;
+ break;
+
+ case 'o':
+ parseoptions(params, optarg);
+ break;
+
+ case 't':
+ getfstype(params, optarg, "-t");
+ break;
+
+ case 'v':
+ params->flags |= IB_VERBOSE;
+ break;
+
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (params->flags & IB_CLEAR && params->flags & IB_EDIT)
+ usage();
+ if (argc < 1 || argc + 2 * !!(params->flags & (IB_CLEAR | IB_EDIT)) > 3)
+ usage();
+
+ /* set missing defaults */
+ if (params->machine == NULL) {
+ if (uname(&utsname) == -1)
+ err(1, "Determine uname");
+ getmachine(params, utsname.machine, "uname()");
+ }
+
+ /* Check that options are supported by this system */
+ unsupported_flags = params->flags & ~params->machine->valid_flags;
+ unsupported_flags &= ~(IB_VERBOSE | IB_NOWRITE | IB_CLEAR | IB_EDIT
+ | IB_FORCE);
+ if (unsupported_flags != 0) {
+ int ndx;
+ for (ndx = 0; options[ndx].name != NULL; ndx++) {
+ if (unsupported_flags & options[ndx].flag) {
+ unsupported_flags &= ~options[ndx].flag;
+ warnx("`-o %s' is not supported for %s",
+ options[ndx].name, params->machine->name);
+ }
+ }
+ if (unsupported_flags & IB_STAGE1START)
+ warnx("`-b bno' is not supported for %s",
+ params->machine->name);
+ if (unsupported_flags & IB_STAGE2START)
+ warnx("`-B bno' is not supported for %s",
+ params->machine->name);
+ unsupported_flags &= ~(IB_STAGE1START | IB_STAGE2START);
+ if (unsupported_flags != 0)
+ warnx("Unknown unsupported flag %#x (coding error!)",
+ unsupported_flags);
+ exit(1);
+ }
+ /* and some illegal combinations */
+ if (params->flags & IB_STAGE1START && params->flags & IB_APPEND) {
+ warnx("Can't use `-b bno' with `-o append'");
+ exit(1);
+ }
+ if (params->flags & IB_CLEAR &&
+ params->flags & (IB_STAGE1START | IB_STAGE2START | IB_APPEND)) {
+ warnx("Can't use `-b bno', `-B bno' or `-o append' with `-c'");
+ exit(1);
+ }
+
+ if (argc >= 3) {
+ params->stage2 = argv[2];
+ }
+
+ params->filesystem = argv[0];
+ if (params->flags & IB_NOWRITE) {
+ op = "only";
+ mode = O_RDONLY;
+ } else {
+ op = "write";
+ mode = O_RDWR;
+ }
+ /* XXX should be specified via option */
+ params->sectorsize = DFL_SECSIZE;
+ if ((params->fsfd = open(params->filesystem, mode, 0600)) == -1)
+ err(1, "Opening file system `%s' read-%s",
+ params->filesystem, op);
+ if (fstat(params->fsfd, ¶ms->fsstat) == -1)
+ err(1, "Examining file system `%s'", params->filesystem);
+ if (params->fstype != NULL) {
+ if (! params->fstype->match(params))
+ errx(1, "File system `%s' is not of type %s",
+ params->filesystem, params->fstype->name);
+ } else {
+ if (params->stage2 != NULL) {
+ params->fstype = &fstypes[0];
+ while (params->fstype->name != NULL &&
+ !params->fstype->match(params))
+ params->fstype++;
+ if (params->fstype->name == NULL)
+ errx(1, "File system `%s' is of an unknown type",
+ params->filesystem);
+ }
+ }
+
+ if (argc >= 2) {
+ if ((params->s1fd = open(argv[1], O_RDONLY, 0600)) == -1)
+ err(1, "Opening primary bootstrap `%s'", argv[1]);
+ if (fstat(params->s1fd, ¶ms->s1stat) == -1)
+ err(1, "Examining primary bootstrap `%s'", argv[1]);
+ if (!S_ISREG(params->s1stat.st_mode))
+ errx(1, "`%s' must be a regular file", argv[1]);
+ params->stage1 = argv[1];
+ }
+ assert(params->machine != NULL);
+
+ if (params->flags & IB_VERBOSE) {
+ printf("File system: %s\n", params->filesystem);
+ if (params->fstype)
+ printf("File system type: %s (blocksize %u, "
+ "needswap %d)\n",
+ params->fstype->name, params->fstype->blocksize,
+ params->fstype->needswap);
+ if (!(params->flags & IB_EDIT))
+ printf("Primary bootstrap: %s\n",
+ (params->flags & IB_CLEAR) ? "(to be cleared)"
+ : params->stage1 ? params->stage1 : "(none)" );
+ if (params->stage2 != NULL)
+ printf("Secondary bootstrap: %s\n", params->stage2);
+ }
+
+ if (params->flags & IB_EDIT) {
+ op = "Edit";
+ rv = params->machine->editboot(params);
+ } else if (params->flags & IB_CLEAR) {
+ op = "Clear";
+ rv = params->machine->clearboot(params);
+ } else {
+ if (argc < 2)
+ errx(EXIT_FAILURE, "Please specify the primary "
+ "bootstrap file");
+ op = "Set";
+ rv = params->machine->setboot(params);
+ }
+ if (rv == 0)
+ errx(1, "%s bootstrap operation failed", op);
+
+ if (S_ISREG(params->fsstat.st_mode)) {
+ if (fsync(params->fsfd) == -1)
+ err(1, "Synchronising file system `%s'",
+ params->filesystem);
+ } else {
+ /* Sync filesystems (to clean in-memory superblock?) */
+ sync();
+ }
+ if (close(params->fsfd) == -1)
+ err(1, "Closing file system `%s'", params->filesystem);
+ if (argc == 2)
+ if (close(params->s1fd) == -1)
+ err(1, "Closing primary bootstrap `%s'",
+ params->stage1);
+
+ exit(0);
+ /* NOTREACHED */
+}
+
+static void
+parseoptions(ib_params *params, const char *option)
+{
+ char *cp;
+ const struct option *opt;
+ int len;
+ unsigned long val;
+
+ assert(params != NULL);
+ assert(option != NULL);
+
+ for (;; option += len) {
+ option += strspn(option, ", \t");
+ if (*option == 0)
+ return;
+ len = strcspn(option, "=,");
+ for (opt = options; opt->name != NULL; opt++) {
+ if (memcmp(option, opt->name, len) == 0
+ && opt->name[len] == 0)
+ break;
+ }
+ if (opt->name == NULL) {
+ len = strcspn(option, ",");
+ warnx("Unknown option `-o %.*s'", len, option);
+ break;
+ }
+ params->flags |= opt->flag;
+ if (opt->type == OPT_BOOL) {
+ if (option[len] != '=')
+ continue;
+ warnx("Option `%s' must not have a value", opt->name);
+ break;
+ }
+ if (option[len] != '=') {
+ warnx("Option `%s' must have a value", opt->name);
+ break;
+ }
+ option += len + 1;
+ len = strcspn(option, ",");
+ switch (opt->type) {
+ case OPT_STRING:
+ len = strlen(option);
+ /* FALLTHROUGH */
+ case OPT_WORD:
+ cp = strdup(option);
+ if (cp == NULL)
+ err(1, "strdup");
+ cp[len] = 0;
+ OPTION(params, char *, opt) = cp;
+ continue;
+ case OPT_INT:
+ val = strtoul(option, &cp, 0);
+ if (cp > option + len || (*cp != 0 && *cp != ','))
+ break;
+ if (val > INT_MAX)
+ break;
+ OPTION(params, int, opt) = (int)val;
+ continue;
+ default:
+ errx(1, "Internal error: option `%s' has invalid type %d",
+ opt->name, opt->type);
+ }
+ warnx("Invalid option value `%s=%.*s'", opt->name, len, option);
+ break;
+ }
+ options_usage();
+ exit(1);
+}
+
+static void
+options_usage(void)
+{
+ int ndx;
+ const char *pfx;
+
+ warnx("Valid options are:");
+ pfx = "\t";
+ for (ndx = 0; options[ndx].name != 0; ndx++) {
+ fprintf(stderr, "%s%s", pfx, options[ndx].name);
+ switch (options[ndx].type) {
+ case OPT_INT:
+ fprintf(stderr, "=number");
+ break;
+ case OPT_WORD:
+ fprintf(stderr, "=word");
+ break;
+ case OPT_STRING:
+ fprintf(stderr, "=string");
+ break;
+ default:
+ break;
+ }
+ if ((ndx % 5) == 4)
+ pfx = ",\n\t";
+ else
+ pfx = ", ";
+ }
+ fprintf(stderr, "\n");
+}
+
+int
+no_setboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ warnx("%s: bootstrap installation is not supported",
+ params->machine->name);
+ return (0);
+}
+
+int
+no_clearboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ warnx("%s: bootstrap removal is not supported",
+ params->machine->name);
+ return (0);
+}
+
+int
+no_editboot(ib_params *params)
+{
+
+ assert(params != NULL);
+
+ warnx("%s: bootstrap editing is not supported",
+ params->machine->name);
+ return (0);
+}
+
+
+static void
+getmachine(ib_params *param, const char *mach, const char *provider)
+{
+ int i;
+
+ assert(param != NULL);
+ assert(mach != NULL);
+ assert(provider != NULL);
+
+ for (i = 0; machines[i] != NULL; i++) {
+ if (machines[i]->name == NULL)
+ continue;
+ if (strcmp(machines[i]->name, mach) == 0) {
+ param->machine = machines[i];
+ return;
+ }
+ }
+ warnx("Invalid machine `%s' from %s", mach, provider);
+ machine_usage();
+ exit(1);
+}
+
+static void
+machine_usage(void)
+{
+ const char *prefix;
+ int i;
+ int col, len;
+ const char *name;
+ int wincol=80;
+#ifdef TIOCGWINSZ
+ struct winsize win;
+
+ if (ioctl(fileno(stderr), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
+ wincol = win.ws_col;
+#endif
+
+ warnx("Supported machines are:");
+ prefix="\t";
+ col = 8 + 3;
+ for (i = 0; machines[i] != NULL; i++) {
+ name = machines[i]->name;
+ if (name == NULL)
+ continue;
+ len = strlen(name);
+ if (col + len > wincol) {
+ prefix=",\n\t";
+ col = -2 + 8 + 3;
+ }
+ col += fprintf(stderr, "%s%s", prefix, name);
+ prefix=", ";
+ }
+ fputs("\n", stderr);
+}
+
+static void
+getfstype(ib_params *param, const char *fstype, const char *provider)
+{
+ int i;
+
+ assert(param != NULL);
+ assert(fstype != NULL);
+ assert(provider != NULL);
+
+ for (i = 0; fstypes[i].name != NULL; i++) {
+ if (strcmp(fstypes[i].name, fstype) == 0) {
+ param->fstype = &fstypes[i];
+ return;
+ }
+ }
+ warnx("Invalid file system type `%s' from %s", fstype, provider);
+ fstype_usage();
+ exit(1);
+}
+
+static void
+fstype_usage(void)
+{
+#ifndef NO_STAGE2
+ const char *prefix;
+ int i;
+
+ warnx("Supported file system types are:");
+#define FSTYPES_PER_LINE 9
+ prefix="\t";
+ for (i = 0; fstypes[i].name != NULL; i++) {
+ if (i && (i % FSTYPES_PER_LINE) == 0)
+ prefix=",\n\t";
+ fprintf(stderr, "%s%s", prefix, fstypes[i].name);
+ prefix=", ";
+ }
+ fputs("\n", stderr);
+#endif
+}
+
+static void
+usage(void)
+{
+ const char *prog;
+
+ prog = getprogname();
+ fprintf(stderr,
+"usage: %s [-fnv] [-B s2bno] [-b s1bno] [-m machine] [-o options]\n"
+"\t\t [-t fstype] filesystem primary [secondary]\n"
+"usage: %s -c [-fnv] [-m machine] [-o options] [-t fstype] filesystem\n"
+"usage: %s -e [-fnv] [-m machine] [-o options] bootstrap\n",
+ prog, prog, prog);
+ machine_usage();
+ fstype_usage();
+ options_usage();
+ exit(1);
+}
--- /dev/null
+/* $NetBSD: installboot.h,v 1.38 2011/06/14 05:35:08 matt Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _INSTALLBOOT_H
+#define _INSTALLBOOT_H
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#include "../../sys/sys/bootblock.h"
+#else
+#include <sys/bootblock.h>
+#include <sys/endian.h>
+#endif
+
+#include <sys/stat.h>
+#include <stdint.h>
+
+typedef enum {
+ /* flags from global options */
+ IB_VERBOSE = 1<<0, /* verbose operation */
+ IB_NOWRITE = 1<<1, /* don't write */
+ IB_CLEAR = 1<<2, /* clear boot block */
+ IB_EDIT = 1<<3, /* edit boot parameters */
+ IB_FORCE = 1<<4, /* Ignore some consistency checks */
+
+ /* flags from -o options */
+ IB_ALPHASUM = 1<<8, /* set Alpha checksum */
+ IB_APPEND = 1<<9, /* append stage 1 to EO(regular)F */
+ IB_SUNSUM = 1<<10, /* set Sun checksum */
+ IB_STAGE1START= 1<<11, /* start block for stage 1 provided */
+ IB_STAGE2START= 1<<12, /* start block for stage 2 provided */
+ IB_COMMAND = 1<<13, /* Amiga commandline option */
+ IB_RESETVIDEO = 1<<14, /* i386 reset video */
+ IB_CONSOLE = 1<<15, /* i386 console */
+ IB_CONSPEED = 1<<16, /* i386 console baud rate */
+ IB_TIMEOUT = 1<<17, /* i386 boot timeout */
+ IB_PASSWORD = 1<<18, /* i386 boot password */
+ IB_KEYMAP = 1<<19, /* i386 console keymap */
+ IB_CONSADDR = 1<<20, /* i386 console io address */
+ IB_MODULES = 1<<21, /* i386: load modules */
+ IB_BOOTCONF = 1<<22, /* i386: read boot.conf */
+} ib_flags;
+
+typedef struct {
+ ib_flags flags; /* flags (see above) */
+ struct ib_mach *machine; /* machine details (see below) */
+ struct ib_fs *fstype; /* file system details (see below) */
+ const char *filesystem; /* name of target file system */
+ int fsfd; /* open fd to filesystem */
+ struct stat fsstat; /* fstat(2) of fsfd */
+ const char *stage1; /* name of stage1 bootstrap */
+ int s1fd; /* open fd to stage1 */
+ struct stat s1stat; /* fstat(2) of s1fd */
+ uint64_t s1start; /* start block of stage1 */
+ const char *stage2; /* name of stage2 bootstrap */
+ uint64_t s2start; /* start block of stage2 */
+ uint32_t sectorsize; /* sector size of target fs */
+ /* parsed -o option=value data */
+ const char *command; /* name of command string */
+ const char *console; /* name of console */
+ int conspeed; /* console baud rate */
+ int consaddr; /* console io address */
+ const char *password; /* boot password */
+ int timeout; /* interactive boot timeout */
+ const char *keymap; /* keyboard translations */
+} ib_params;
+
+typedef struct {
+ uint64_t block;
+ uint32_t blocksize;
+} ib_block;
+
+struct ib_mach {
+ const char *name;
+ int (*setboot) (ib_params *);
+ int (*clearboot) (ib_params *);
+ int (*editboot) (ib_params *);
+ ib_flags valid_flags;
+};
+
+struct ib_fs {
+ /* compile time parameters */
+ const char *name;
+ int (*match) (ib_params *);
+ int (*findstage2) (ib_params *, uint32_t *, ib_block *);
+ /* run time fs specific parameters */
+ uint32_t blocksize;
+ uint32_t needswap;
+ off_t sblockloc; /* location of superblock */
+ off_t offset; /* file system offset (e.g. RAID) */
+};
+
+typedef enum {
+ BBINFO_BIG_ENDIAN = 0,
+ BBINFO_LITTLE_ENDIAN = 1,
+} bbinfo_endian;
+
+struct bbinfo_params {
+ const char *magic; /* magic string to look for */
+ uint32_t offset; /* offset to write start of stage1 */
+ uint32_t blocksize; /* blocksize of stage1 */
+ uint32_t maxsize; /* max size of stage1 */
+ uint32_t headeroffset; /*
+ * header offset (relative to offset)
+ * to read stage1 into
+ */
+ bbinfo_endian endian;
+};
+
+extern struct ib_mach * const machines[];
+extern struct ib_fs fstypes[];
+
+ /* installboot.c */
+uint16_t compute_sunsum(const uint16_t *);
+int set_sunsum(ib_params *, uint16_t *, uint16_t);
+int no_setboot(ib_params *);
+int no_clearboot(ib_params *);
+int no_editboot(ib_params *);
+
+ /* bbinfo.c */
+int shared_bbinfo_clearboot(ib_params *, struct bbinfo_params *,
+ int (*)(ib_params *, struct bbinfo_params *, uint8_t *));
+int shared_bbinfo_setboot(ib_params *, struct bbinfo_params *,
+ int (*)(ib_params *, struct bbinfo_params *, uint8_t *));
+
+ /* fstypes.c */
+int hardcode_stage2(ib_params *, uint32_t *, ib_block *);
+int ffs_match(ib_params *);
+int ffs_findstage2(ib_params *, uint32_t *, ib_block *);
+int raid_match(ib_params *);
+int raw_match(ib_params *);
+int raw_findstage2(ib_params *, uint32_t *, ib_block *);
+int ext2fs_match(ib_params *);
+int ext2fs_findstage2(ib_params *, uint32_t *, ib_block *);
+
+ /* machines.c */
+extern struct ib_mach ib_mach_alpha;
+extern struct ib_mach ib_mach_amd64;
+extern struct ib_mach ib_mach_amiga;
+extern struct ib_mach ib_mach_ews4800mips;
+extern struct ib_mach ib_mach_hp300;
+extern struct ib_mach ib_mach_hp700;
+extern struct ib_mach ib_mach_i386;
+extern struct ib_mach ib_mach_landisk;
+extern struct ib_mach ib_mach_macppc;
+extern struct ib_mach ib_mach_news68k;
+extern struct ib_mach ib_mach_newsmips;
+extern struct ib_mach ib_mach_next68k;
+extern struct ib_mach ib_mach_pmax;
+extern struct ib_mach ib_mach_sparc;
+extern struct ib_mach ib_mach_sparc64;
+extern struct ib_mach ib_mach_sun2;
+extern struct ib_mach ib_mach_sun3;
+extern struct ib_mach ib_mach_vax;
+extern struct ib_mach ib_mach_x68k;
+
+#endif /* _INSTALLBOOT_H */
--- /dev/null
+/* $NetBSD: machines.c,v 1.38 2011/06/14 05:35:08 matt Exp $ */
+
+/*-
+ * Copyright (c) 2002-2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: machines.c,v 1.38 2011/06/14 05:35:08 matt Exp $");
+#endif /* !__lint */
+
+#include <sys/types.h>
+#include "installboot.h"
+
+/*
+ * Define these here so they end up as zero-filled bss if installboot
+ * isn't built with all the architectures defined.
+ * A lot simpler that conditionally including the definitions themselves.
+ */
+struct ib_mach
+ ib_mach_alpha,
+ ib_mach_amd64,
+ ib_mach_amiga,
+ ib_mach_emips,
+ ib_mach_ews4800mips,
+ ib_mach_hp300,
+ ib_mach_hp700,
+ ib_mach_i386,
+ ib_mach_landisk,
+ ib_mach_macppc,
+ ib_mach_news68k,
+ ib_mach_newsmips,
+ ib_mach_next68k,
+ ib_mach_pmax,
+ ib_mach_sparc,
+ ib_mach_sparc64,
+ ib_mach_sun2,
+ ib_mach_sun3,
+ ib_mach_vax,
+ ib_mach_x68k;
+
+struct ib_mach * const machines[] = {
+ &ib_mach_alpha,
+ &ib_mach_amd64,
+ &ib_mach_amiga,
+ &ib_mach_emips,
+ &ib_mach_ews4800mips,
+ &ib_mach_hp300,
+ &ib_mach_hp700,
+ &ib_mach_i386,
+ &ib_mach_landisk,
+ &ib_mach_macppc,
+ &ib_mach_news68k,
+ &ib_mach_newsmips,
+ &ib_mach_next68k,
+ &ib_mach_pmax,
+ &ib_mach_sparc,
+ &ib_mach_sparc64,
+ &ib_mach_sun2,
+ &ib_mach_sun3,
+ &ib_mach_vax,
+ &ib_mach_x68k,
+ NULL
+};
+
+#if 0
+ { "shark", no_setboot, no_clearboot, no_editboot, 0 },
+#endif
--- /dev/null
+/* $NetBSD: sum.c,v 1.5 2010/01/14 16:27:49 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Ross Harvey. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ross Harvey
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(__lint)
+__RCSID("$NetBSD: sum.c,v 1.5 2010/01/14 16:27:49 tsutsui Exp $");
+#endif /* !__lint */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "installboot.h"
+
+
+uint16_t
+compute_sunsum(const uint16_t *bb16)
+{
+ uint16_t i, s;
+
+ assert(bb16 != NULL);
+
+ s = 0;
+ for (i = 0; i < 255; ++i)
+ s ^= bb16[i];
+ return (s);
+}
+
+int
+set_sunsum(ib_params *params, uint16_t *bb16, uint16_t sum)
+{
+
+ assert(params != NULL);
+ assert(bb16 != NULL);
+
+#define SUNSUM_OFFSET 255
+ if (params->flags & IB_VERBOSE) {
+ printf("Old Sun checksum: 0x%04x\n",
+ be16toh(bb16[SUNSUM_OFFSET]));
+ printf("Recalculated Sun checksum: 0x%04x\n", be16toh(sum));
+ }
+ // XXX: does this need to be big endian?
+ bb16[SUNSUM_OFFSET] = sum;
+ return (1);
+}