Index: src/usr.sbin/installboot/Makefile =================================================================== RCS file: /cvsroot/basesrc/usr.sbin/installboot/Makefile,v retrieving revision 1.10 diff -u -r1.10 Makefile --- src/usr.sbin/installboot/Makefile 2002/04/11 07:56:13 1.10 +++ src/usr.sbin/installboot/Makefile 2002/04/17 04:02:48 @@ -2,14 +2,15 @@ # PROG= installboot -SRCS= installboot.c sum.c machines.c \ - alpha.c pmax.c sparc64.c vax.c +SRCS= installboot.c sum.c machines.c fstypes.c ffs.c ffs_bswap.c \ + alpha.c pmax.c sparc64.c sun68k.c vax.c MAN= installboot.8 WARNS?= 3 -CPPFLAGS+= -I${.CURDIR} -.PATH: ${.CURDIR}/arch +UFSSRC= ${.CURDIR}/../../sys/ufs +CPPFLAGS+= -I${.CURDIR} -I${.CURDIR}/../.. +.PATH: ${.CURDIR}/arch ${UFSSRC}/ffs .ifndef HOSTPROG # list of MACHINEs to enable the compat symlink /usr/mdec/installboot Index: src/usr.sbin/installboot/installboot.8 =================================================================== RCS file: /cvsroot/basesrc/usr.sbin/installboot/installboot.8,v retrieving revision 1.8 diff -u -r1.8 installboot.8 --- src/usr.sbin/installboot/installboot.8 2002/04/12 06:50:41 1.8 +++ src/usr.sbin/installboot/installboot.8 2002/04/17 04:02:48 @@ -171,6 +171,7 @@ .Sy alpha , .Sy pmax , .Sy sparc64 , +.Sy sun2 , .Sy vax .Ed . @@ -337,6 +338,7 @@ back-ends: Simon Burge (pmax), Chris Demetriou (alpha), +Matthew Fredette (sun2), Matthew Green (sparc64), Ross Harvey (alpha), and Index: src/usr.sbin/installboot/installboot.c =================================================================== RCS file: /cvsroot/basesrc/usr.sbin/installboot/installboot.c,v retrieving revision 1.5 diff -u -r1.5 installboot.c --- src/usr.sbin/installboot/installboot.c 2002/04/12 06:50:41 1.5 +++ src/usr.sbin/installboot/installboot.c 2002/04/17 04:02:48 @@ -56,6 +56,7 @@ int main(int, char *[]); static int getmachine(ib_params *, const char *, const char *); +static int getfstype(ib_params *, const char *, const char *); static void usage(void); static ib_params installboot_params; @@ -118,7 +119,8 @@ break; case 't': - params->fstype = optarg; // XXX: validate? + if (! getfstype(params, optarg, "-t")) + exit(1); break; case 'v': @@ -146,7 +148,6 @@ if (! getmachine(params, utsname.machine, "uname()")) exit(1); } - // XXX: set default params->fstype params->filesystem = argv[0]; if (params->flags & IB_NOWRITE) { @@ -159,6 +160,19 @@ if ((params->fsfd = open(params->filesystem, mode, 0600)) == -1) err(1, "Opening file system `%s' read-%s", params->filesystem, op); + if (params->fstype != NULL) { + if (! params->fstype->match(params)) + err(1, "File system `%s' is not of type %s", + params->filesystem, params->fstype->name); + } else { + params->fstype = &fstypes[0]; + while (params->fstype->name != NULL && + ! params->fstype->match(params)) + params->fstype++; + if (params->fstype->name == NULL) + err(1, "File system `%s' is of an unknown type", + params->filesystem); + } if (argc >= 2) { params->stage1 = argv[1]; @@ -286,6 +300,34 @@ fputs("\n", stderr); } if ((i % MACHS_PER_LINE) != 0) + fputs("\n", stderr); + return (0); +} + +static int +getfstype(ib_params *param, const char *fstype, const char *provider) +{ + int i; + + assert(param != NULL); + assert(fstype != NULL); + + for (i = 0; fstypes[i].name != NULL; i++) { + if (strcmp(fstypes[i].name, fstype) == 0) { + param->fstype = &fstypes[i]; + return (1); + } + } + warnx("Invalid file system type `%s' from %s", fstype, provider); + warnx("Supported file system types are:"); +#define FSTYPES_PER_LINE 10 + for (i = 0; fstypes[i].name != NULL; i++) { + fputs((i % FSTYPES_PER_LINE) ? ", " : "\t", stderr); + fputs(fstypes[i].name, stderr); + if ((i % FSTYPES_PER_LINE) == (FSTYPES_PER_LINE - 1)) + fputs("\n", stderr); + } + if ((i % FSTYPES_PER_LINE) != 0) fputs("\n", stderr); return (0); } Index: src/usr.sbin/installboot/installboot.h =================================================================== RCS file: /cvsroot/basesrc/usr.sbin/installboot/installboot.h,v retrieving revision 1.4 diff -u -r1.4 installboot.h --- src/usr.sbin/installboot/installboot.h 2002/04/12 06:50:41 1.4 +++ src/usr.sbin/installboot/installboot.h 2002/04/17 04:02:48 @@ -59,7 +59,7 @@ typedef struct { ib_flags flags; struct ib_mach *machine; - const char *fstype; // XXX replace with struct *? + struct ib_fs *fstype; const char *filesystem; int fsfd; const char *stage1; @@ -68,6 +68,11 @@ long startblock; } ib_params; +typedef struct { + long db; + long blksize; +} ib_block; + struct ib_mach { const char *name; int (*parseopt) (ib_params *, const char *); @@ -75,8 +80,15 @@ int (*clearboot) (ib_params *); }; +struct ib_fs { + const char *name; + int (*match) (ib_params *); + int (*findstage2) (ib_params *, long *, ib_block *); +}; extern struct ib_mach machines[]; + +extern struct ib_fs fstypes[]; int parseoptionflag(ib_params *, const char *, ib_flags); u_int16_t compute_sunsum(const u_int16_t *); Index: src/usr.sbin/installboot/machines.c =================================================================== RCS file: /cvsroot/basesrc/usr.sbin/installboot/machines.c,v retrieving revision 1.5 diff -u -r1.5 machines.c --- src/usr.sbin/installboot/machines.c 2002/04/11 07:56:13 1.5 +++ src/usr.sbin/installboot/machines.c 2002/04/17 04:02:48 @@ -47,6 +47,8 @@ int pmax_clearboot(ib_params *); int sparc64_setboot(ib_params *); int sparc64_clearboot(ib_params *); +int sun68k_setboot(ib_params *); +int sun68k_clearboot(ib_params *); int vax_parseopt(ib_params *, const char *); int vax_setboot(ib_params *); int vax_clearboot(ib_params *); @@ -57,6 +59,7 @@ { "pmax", pmax_parseopt, pmax_setboot, pmax_clearboot }, { "shark", no_parseopt, no_setboot, no_clearboot }, { "sparc64", no_parseopt, sparc64_setboot, sparc64_clearboot }, + { "sun2", no_parseopt, sun68k_setboot, sun68k_clearboot }, { "vax", vax_parseopt, vax_setboot, vax_clearboot }, { 0, 0, 0, 0 }, }; --- /dev/null Tue Mar 12 14:00:23 2002 +++ src/usr.sbin/installboot/fstypes.c Tue Apr 16 03:46:39 2002 @@ -0,0 +1,48 @@ +/* $NetBSD$ */ + +/*- + * 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. + * 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. + */ + +#include +#include "installboot.h" + +int ffs_match(ib_params *); +int ffs_findstage2(ib_params *, long *, ib_block *); + +struct ib_fs fstypes[] = { + { "ffs", ffs_match, ffs_findstage2 }, + { 0, 0, 0 } +}; --- /dev/null Tue Mar 12 14:00:23 2002 +++ src/usr.sbin/installboot/ffs.c Tue Apr 16 17:44:22 2002 @@ -0,0 +1,352 @@ +/* $NetBSD$ */ + +/*- + * 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. + * 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. + */ + +#include +#if defined(__RCSID) && !defined(__lint) +__RCSID("$NetBSD$"); +#endif /* !__lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "installboot.h" + +#undef DIRBLKSIZ + +#include +#include +#include +#include +#include + +int ffs_match(ib_params *); +int ffs_findstage2(ib_params *, long *, ib_block *); + +/* This reads a disk block from the filesystem. */ +static int +ffs_read_disk_block(ib_params *params, int32_t blkno, int size, char *blk) +{ + int rv; + + assert(params->filesystem != NULL); + assert(params->fsfd != -1); + assert(blkno > 0); + assert(size > 0); + assert(blk != NULL); + + rv = pread(params->fsfd, blk, size, blkno * DEV_BSIZE); + if (rv == -1) { + warn("Reading block %d in `%s'", blkno, params->filesystem); + return (0); + } else if (rv != size) { + warnx("Reading block %d in `%s': short read", 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(ib_params *params, u_int32_t ino, + int (*callback)(ib_params *, void *, long, long, int), void *state) +{ + char sbbuf[SBSIZE]; + struct fs *fs; + int needswap; + char inodebuf[MAXBSIZE]; + struct dinode *inode; +#define LEVELS 4 + struct { + ufs_daddr_t *blknums; + unsigned long blkcount; + char diskbuf[MAXBSIZE]; + } level[LEVELS]; + int level_i; + ufs_daddr_t blk, lblk, nblk; + int rv; + + /* Read the superblock. */ + if (! ffs_read_disk_block(params, SBLOCK, SBSIZE, sbbuf)) + return (0); + fs = (struct fs *)sbbuf; + needswap = 0; + if (fs->fs_magic == htole32(FS_MAGIC)) { +#if BYTE_ORDER == BIG_ENDIAN + needswap = 1; +#endif + } else if (fs->fs_magic == htobe32(FS_MAGIC)) { +#if BYTE_ORDER == LITTLE_ENDIAN + needswap = 1; +#endif + } else + return (0); + if (needswap) + ffs_sb_swap(fs, fs); + + /* Sanity check the superblock. */ + if (fs->fs_magic != FS_MAGIC) { + warnx("Bad superblock magic number in `%s'", + params->filesystem); + return (0); + } + 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)), + fs->fs_bsize, inodebuf)) + return (0); + inode = (struct dinode *)inodebuf; + inode += ino_to_fsbo(fs, ino); + if (needswap) + ffs_dinode_swap(inode, inode); + + /* 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 (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), + fs->fs_bsize, level[level_i].diskbuf)) + return (0); + level[level_i].blknums = + (ufs_daddr_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), dblksize(fs, inode, lblk)); +#endif + rv = (*callback)(params, state, + fsbtodb(fs, blk), dblksize(fs, inode, lblk), needswap); + lblk++; + nblk--; + if (rv != 1) + return (rv); + } + + if (nblk != 0) { + warnx("Inode %d in `%s' ran out of blocks?", 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, + long blk, long blksize, int needswap) +{ + char dirbuf[MAXBSIZE]; + struct direct *de, *ede; + u_int32_t ino; + + /* 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_ino; + if (needswap) { + ino = bswap32(ino); + de->d_reclen = bswap16(de->d_reclen); + } + if (ino != 0 && strcmp(de->d_name, params->stage2) == 0) { + *((u_int32_t *)_ino) = ino; + return (2); + } + de = (struct direct *)((char *)de + de->d_reclen); + } + + return (1); +} + +struct findblks_state { + long maxblk; + long nblk; + ib_block *blocks; +}; + +/* This callback records the blocks of the secondary bootstrap. */ +static int +ffs_findstage2_blocks(ib_params *params, void *_state, + long blk, long blksize, int needswap) +{ + struct findblks_state *state = _state; + + if (state->nblk == state->maxblk) { + warnx("Secondary bootstrap `%s' has too many blocks " \ + "(max %ld)\n", params->stage2, state->maxblk); + return (0); + } + state->blocks[state->nblk].db = blk; + state->blocks[state->nblk].blksize = blksize; + state->nblk++; + return (1); +} + + /* publically visible functions */ + +int +ffs_match(ib_params *params) +{ + char sbbuf[SBSIZE]; + struct fs *fs; + + /* Read and check the superblock. */ + if (! ffs_read_disk_block(params, SBLOCK, SBSIZE, sbbuf)) + return (0); + fs = (struct fs *)sbbuf; + if (fs->fs_magic == htole32(FS_MAGIC) || + fs->fs_magic == htobe32(FS_MAGIC)) + return (1); + + return (0); +} + +int +ffs_findstage2(ib_params *params, long *maxblk, ib_block *blocks) +{ + int rv; + u_int32_t ino; + struct findblks_state state; + + assert (params->stage2 != NULL); + + /* 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); + return (0); + } + + /* Get the inode number of the secondary bootstrap. */ + rv = ffs_find_disk_blocks(params, ROOTINO, ffs_findstage2_ino, &ino); + if (rv != 2) + return (0); + + /* Record the disk blocks of the secondary bootstrap. */ + state.maxblk = *maxblk; + state.nblk = 0; + state.blocks = blocks; + rv = ffs_find_disk_blocks(params, ino, ffs_findstage2_blocks, &state); + if (! rv) + return (0); + + *maxblk = state.nblk; + return (1); +} --- /dev/null Tue Mar 12 14:00:23 2002 +++ src/usr.sbin/installboot/arch/sun68k.c Tue Apr 16 17:44:02 2002 @@ -0,0 +1,314 @@ +/* $NetBSD$ */ + +/*- + * 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. + * 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) 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. + * 3. 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) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * 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. + */ + +#include +#if defined(__RCSID) && !defined(__lint) +__RCSID("$NetBSD$"); +#endif /* !__lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "installboot.h" + +#include + +int sun68k_setboot(ib_params *); +int sun68k_clearboot(ib_params *); + +#define SUN68K_BOOT_BLOCK_OFFSET DEV_BSIZE +#define SUN68K_BOOT_BLOCK_BLOCKSIZE DEV_BSIZE +#define SUN68K_BOOT_BLOCK_MAX_SIZE (DEV_BSIZE * 15) + +int +sun68k_clearboot(ib_params *params) +{ + char bb[SUN68K_BOOT_BLOCK_MAX_SIZE]; + ssize_t rv; + + assert(params != NULL); + assert(params->fsfd != -1); + assert(params->filesystem != NULL); + + if (params->flags & IB_STARTBLOCK) { + warnx("Can't use `-b bno' with `-c'"); + return (0); + } + /* first check that it _could_ exist here */ + rv = pread(params->fsfd, &bb, sizeof bb, SUN68K_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), SUN68K_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); +} + +int +sun68k_setboot(ib_params *params) +{ + struct stat bootstrapsb; + char bb[SUN68K_BOOT_BLOCK_MAX_SIZE]; + int startblock, retval; + ssize_t rv; + size_t bbi; + struct bbinfo *bbinfop; /* bbinfo in prototype image */ + long maxblk, nblk, blk_i; + ib_block *blocks = NULL; + + assert(params != NULL); + assert(params->fsfd != -1); + assert(params->filesystem != NULL); + assert(params->fstype != NULL); + assert(params->s1fd != -1); + assert(params->stage1 != NULL); + + if (params->stage2 == NULL) { + warnx("You must provide a secondary bootstrap"); + return (0); + } + + 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; + } + if (bootstrapsb.st_size > sizeof bb) { + warnx("`%s' cannot be larger than %d bytes", + params->stage1, sizeof bb); + goto done; + } + + memset(&bb, 0, SUN68K_BOOT_BLOCK_MAX_SIZE); + rv = read(params->s1fd, &bb, sizeof bb); + 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 + 1, "ELF", strlen("ELF")) == 0) { + warn("`%s' is an ELF executable; need raw binary", + params->stage1); + goto done; + } + + /* Look for the bbinfo structure. */ + for (bbi = 0; bbi < sizeof bb; bbi += sizeof(uint32_t)) { + bbinfop = (void *) (bb + bbi); + if (memcmp(bbinfop->bbi_magic, BBINFO_MAGIC, + BBINFO_MAGICSIZE) == 0) + break; + } + if (bbi >= sizeof bb) { + warn("`%s' does not have a bbinfo structure\n", + params->stage1); + goto done; + } + maxblk = be32toh(bbinfop->bbi_block_count); + + /* 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; + } + + /* 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 = htobe32(nblk); + bbinfop->bbi_block_size = htobe32(blocks[0].blksize); + for (blk_i = 0; blk_i < nblk; blk_i++) { + bbinfop->bbi_block_table[blk_i] = + htobe32(blocks[blk_i].db); + if (blocks[blk_i].blksize < blocks[0].blksize && + blk_i + 1 != nblk) { + warnx("Secondary bootstrap `%s' blocks do not have " \ + "a uniform size\n", params->stage2); + goto done; + } + } + + if (params->flags & IB_STARTBLOCK) + startblock = params->startblock; + else + startblock = SUN68K_BOOT_BLOCK_OFFSET / + SUN68K_BOOT_BLOCK_BLOCKSIZE; + + if (params->flags & IB_VERBOSE) { + printf("Bootstrap start sector: %#x\n", startblock); + printf("Bootstrap byte count: %#x\n", (unsigned)rv); + printf("Bootstrap block table: %ld entries avail, %ld used:", + maxblk, nblk); + for (blk_i = 0; blk_i < nblk; blk_i++) + printf(" %ld", blocks[blk_i].db); + 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, SUN68K_BOOT_BLOCK_MAX_SIZE, + startblock * SUN68K_BOOT_BLOCK_BLOCKSIZE); + if (rv == -1) { + warn("Writing `%s'", params->filesystem); + goto done; + } else if (rv != SUN68K_BOOT_BLOCK_MAX_SIZE) { + warnx("Writing `%s': short write", params->filesystem); + goto done; + } else + retval = 1; + + done: + if (blocks != NULL) + free (blocks); + return (retval); +}