Import usr.sbin/installboot.

This commit is contained in:
Evgeniy Ivanov 2012-01-10 12:46:52 +04:00 committed by Ben Gras
parent 4c4c045f87
commit 9f8e6353e5
28 changed files with 7382 additions and 0 deletions

View file

@ -33,6 +33,7 @@ usr.bin/seq src/usr.bin/seq
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

View file

@ -0,0 +1,54 @@
# $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>

View file

@ -0,0 +1,451 @@
/* $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));
}

View file

@ -0,0 +1,173 @@
/* $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;
}

View file

@ -0,0 +1,145 @@
/* $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);
}

View file

@ -0,0 +1,62 @@
#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;
}

View file

@ -0,0 +1,214 @@
/* $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;
}

View file

@ -0,0 +1,220 @@
/* $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);
}

View file

@ -0,0 +1,552 @@
/* $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;
}

View file

@ -0,0 +1,250 @@
/* $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;
}

View file

@ -0,0 +1,186 @@
/* $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);
}

View file

@ -0,0 +1,166 @@
/* $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);
}

View file

@ -0,0 +1,267 @@
/* $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;
}

View file

@ -0,0 +1,369 @@
/* $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);
}

View file

@ -0,0 +1,128 @@
/* $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);
}

View file

@ -0,0 +1,185 @@
/* $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);
}

View file

@ -0,0 +1,85 @@
/* $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));
}

View file

@ -0,0 +1,316 @@
/* $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);
}

View file

@ -0,0 +1,181 @@
/* $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);
}

View file

@ -0,0 +1,330 @@
/* $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);
}

View file

@ -0,0 +1,468 @@
/* $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;
}

592
usr.sbin/installboot/ffs.c Normal file
View file

@ -0,0 +1,592 @@
/* $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);
}

View file

@ -0,0 +1,133 @@
/* $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

View file

@ -0,0 +1,895 @@
.\" $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.

View file

@ -0,0 +1,569 @@
/* $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, &params->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, &params->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);
}

View file

@ -0,0 +1,185 @@
/* $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 */

View file

@ -0,0 +1,97 @@
/* $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

108
usr.sbin/installboot/sum.c Normal file
View file

@ -0,0 +1,108 @@
/* $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);
}