diff options
Diffstat (limited to 'sys/boot/i386/installboot/installboot.c')
| -rw-r--r-- | sys/boot/i386/installboot/installboot.c | 433 |
1 files changed, 0 insertions, 433 deletions
diff --git a/sys/boot/i386/installboot/installboot.c b/sys/boot/i386/installboot/installboot.c deleted file mode 100644 index 12e75bc89883..000000000000 --- a/sys/boot/i386/installboot/installboot.c +++ /dev/null @@ -1,433 +0,0 @@ -/* $NetBSD: installboot.c,v 1.5 1997/11/01 06:49:50 lukem Exp $ */ - -/* - * Copyright (c) 1994 Paul Kranenburg - * All rights reserved. - * Copyright (c) 1996, 1997 - * Matthias Drochner. All rights reserved. - * Copyright (c) 1996, 1997 - * Perry E. Metzger. 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 Paul Kranenburg. - * This product includes software developed for the NetBSD Project - * by Matthias Drochner. - * This product includes software developed for the NetBSD Project - * by Perry E. Metzger. - * 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. - */ - -#include <sys/param.h> -#include <sys/disklabel.h> -/* #include <sys/dkio.h> */ -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> -#include <ufs/ffs/fs.h> -#include <sys/errno.h> -#include <err.h> -#include <a.out.h> -#include <fcntl.h> -#include <nlist.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> - -#include "installboot.h" - -#include "bbinfo.h" - -#define DEFBBLKNAME "loader" - -struct fraglist *fraglist; - -struct nlist nl[] = { -#define X_fraglist 0 - {{"_fraglist"}}, - {{NULL}} -}; - -int verbose = 0; - -char * -loadprotoblocks(fname, size) - char *fname; - long *size; -{ - int fd; - size_t tdsize; /* text+data size */ - size_t bbsize; /* boot block size (block aligned) */ - char *bp; - struct nlist *nlp; - struct exec eh; - - fd = -1; - bp = NULL; - - /* Locate block number array in proto file */ - if (nlist(fname, nl) != 0) { - warnx("nlist: %s: symbols not found", fname); - return NULL; - } - /* Validate symbol types (global text!). */ - for (nlp = nl; nlp->n_un.n_name; nlp++) { - if (nlp->n_type != (N_TEXT | N_EXT)) { - warnx("nlist: %s: wrong type", nlp->n_un.n_name); - return NULL; - } - } - - if ((fd = open(fname, O_RDONLY)) < 0) { - warn("open: %s", fname); - return NULL; - } - if (read(fd, &eh, sizeof(eh)) != sizeof(eh)) { - warn("read: %s", fname); - goto bad; - } - if (N_GETMAGIC(eh) != OMAGIC) { - warn("bad magic: 0x%lx", eh.a_midmag); - goto bad; - } - /* - * We need only text and data. - */ - tdsize = eh.a_text + eh.a_data; - bbsize = roundup(tdsize, DEV_BSIZE); - - if ((bp = calloc(bbsize, 1)) == NULL) { - warnx("malloc: %s: no memory", fname); - goto bad; - } - /* read the rest of the file. */ - if (read(fd, bp, tdsize) != tdsize) { - warn("read: %s", fname); - goto bad; - } - *size = bbsize; /* aligned to DEV_BSIZE */ - - fraglist = (struct fraglist *) (bp + nl[X_fraglist].n_value); - - if (fraglist->magic != FRAGLISTMAGIC) { - warnx("invalid bootblock version"); - goto bad; - } - if (verbose) { - fprintf(stderr, "%s: entry point %#lx\n", fname, eh.a_entry); - fprintf(stderr, "proto bootblock size %ld\n", *size); - fprintf(stderr, "room for %d filesystem blocks at %#lx\n", - fraglist->maxentries, nl[X_fraglist].n_value); - } - close(fd); - return bp; - -bad: - if (bp) - free(bp); - if (fd >= 0) - close(fd); - return NULL; -} - -static int -devread(fd, buf, blk, size, msg) - int fd; - void *buf; - daddr_t blk; - size_t size; - char *msg; -{ - if (lseek(fd, dbtob(blk), SEEK_SET) != dbtob(blk)) { - warn("%s: devread: lseek", msg); - return (1); - } - if (read(fd, buf, size) != size) { - warn("%s: devread: read", msg); - return (1); - } - return (0); -} - -/* add file system blocks to fraglist */ -static int -add_fsblk(fs, blk, blcnt) - struct fs *fs; - daddr_t blk; - int blcnt; -{ - int nblk; - - /* convert to disk blocks */ - blk = fsbtodb(fs, blk); - nblk = fs->fs_bsize / DEV_BSIZE; - if (nblk > blcnt) - nblk = blcnt; - - if (verbose) - fprintf(stderr, "dblk: %d, num: %d\n", blk, nblk); - - /* start new entry or append to previous? */ - if (!fraglist->numentries || - (fraglist->entries[fraglist->numentries - 1].offset - + fraglist->entries[fraglist->numentries - 1].num != blk)) { - - /* need new entry */ - if (fraglist->numentries > fraglist->maxentries - 1) { - errx(1, "not enough fragment space in bootcode\n"); - return(-1); - } - - fraglist->entries[fraglist->numentries].offset = blk; - fraglist->entries[fraglist->numentries++].num = 0; - } - fraglist->entries[fraglist->numentries - 1].num += nblk; - - return (blcnt - nblk); -} - -static char sblock[SBSIZE]; - -int -loadblocknums(diskdev, inode) - char *diskdev; - ino_t inode; -{ - int devfd = -1; - struct fs *fs; - char *buf = 0; - daddr_t blk, *ap; - struct dinode *ip; - int i, ndb; - int allok = 0; - - devfd = open(diskdev, O_RDONLY, 0); - if (devfd < 0) { - warn("open raw partition"); - return (1); - } - /* Read superblock */ - if (devread(devfd, sblock, SBLOCK, SBSIZE, "superblock")) - goto out; - fs = (struct fs *) sblock; - - if (fs->fs_magic != FS_MAGIC) { - warnx("invalid super block"); - goto out; - } - /* Read inode */ - if ((buf = malloc(fs->fs_bsize)) == NULL) { - warnx("No memory for filesystem block"); - goto out; - } - blk = fsbtodb(fs, ino_to_fsba(fs, inode)); - if (devread(devfd, buf, blk, fs->fs_bsize, "inode")) - goto out; - ip = (struct dinode *) (buf) + ino_to_fsbo(fs, inode); - - /* - * Have the inode. Figure out how many blocks we need. - */ - ndb = ip->di_size / DEV_BSIZE; /* size is rounded! */ - - if (verbose) - fprintf(stderr, "Will load %d blocks.\n", ndb); - - /* - * Get the block numbers, first direct blocks - */ - ap = ip->di_db; - for (i = 0; i < NDADDR && *ap && ndb > 0; i++, ap++) - ndb = add_fsblk(fs, *ap, ndb); - - if (ndb > 0) { - /* - * Just one level of indirections; there isn't much room - * for more in the 1st-level bootblocks anyway. - */ - blk = fsbtodb(fs, ip->di_ib[0]); - if (devread(devfd, buf, blk, fs->fs_bsize, "indirect block")) - goto out; - ap = (daddr_t *) buf; - for (; i < NINDIR(fs) && *ap && ndb > 0; i++, ap++) { - ndb = add_fsblk(fs, *ap, ndb); - } - } - - if (!ndb) - allok = 1; - else { - if (ndb > 0) - warnx("too many fs blocks"); - /* else, ie ndb < 0, add_fsblk returned error */ - goto out; - } - -out: - if (buf) - free(buf); - if (devfd >= 0) - close(devfd); - return (!allok); -} - -static void -usage() -{ - fprintf(stderr, - "usage: installboot [-n] [-v] [-f] <boot> <device>\n"); - exit(1); -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - char c, *bp = 0; - long size; - ino_t inode = (ino_t) -1; - int devfd = -1; - struct disklabel dl; - int bsdoffs; - int i, res; - int forceifnolabel = 0; - char *bootblkname = DEFBBLKNAME; - int nowrite = 0; - int allok = 0; - - while ((c = getopt(argc, argv, "vnf")) != -1) { - switch (c) { - case 'n': - /* Do not actually write the bootblock to disk */ - nowrite = 1; - break; - case 'v': - /* Chat */ - verbose = 1; - break; - case 'f': - /* assume zero offset if no disklabel */ - forceifnolabel = 1; - break; - default: - usage(); - } - } - - if (argc - optind != 2) { - usage(); - } - - bp = loadprotoblocks(argv[optind], &size); - if (!bp) - errx(1, "error reading bootblocks"); - - fraglist->numentries = 0; - - /* do we need the fraglist? */ - if (size > fraglist->loadsz * DEV_BSIZE) { - - inode = createfileondev(argv[optind + 1], bootblkname, - bp + fraglist->loadsz * DEV_BSIZE, - size - fraglist->loadsz * DEV_BSIZE); - if (inode == (ino_t) - 1) - goto out; - - /* paranoia */ - sync(); - sleep(3); - - if (loadblocknums(argv[optind + 1], inode)) - goto out; - - size = fraglist->loadsz * DEV_BSIZE; - /* size to be written to bootsect */ - } - - devfd = open(argv[optind + 1], O_RDWR, 0); - if (devfd < 0) { - warn("open raw partition RW"); - goto out; - } - if (ioctl(devfd, DIOCGDINFO, &dl) < 0) { - if ((errno == EINVAL) || (errno == ENOTTY)) { - if (forceifnolabel) - bsdoffs = 0; - else { - warnx("no disklabel, use -f to install anyway"); - goto out; - } - } else { - warn("get disklabel"); - goto out; - } - } else { - char c = argv[optind + 1][strlen(argv[optind + 1]) - 1]; -#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z') - if(!isvalidpart(c) || (c - 'a') >= dl.d_npartitions) { - warnx("invalid partition"); - goto out; - } - bsdoffs = dl.d_partitions[c - 'a'].p_offset; - } - if (verbose) - fprintf(stderr, "BSD partition starts at sector %d\n", bsdoffs); - - /* - * add offset of BSD partition to fraglist entries - */ - for (i = 0; i < fraglist->numentries; i++) - fraglist->entries[i].offset += bsdoffs; - - if (!nowrite) { - /* - * write first blocks (max loadsz) to start of BSD partition, - * skip disklabel (in second disk block) - */ - lseek(devfd, 0, SEEK_SET); - res = write(devfd, bp, DEV_BSIZE); - if (res < 0) { - warn("final write1"); - goto out; - } - lseek(devfd, 2 * DEV_BSIZE, SEEK_SET); - res = write(devfd, bp + 2 * DEV_BSIZE, size - 2 * DEV_BSIZE); - if (res < 0) { - warn("final write2"); - goto out; - } - } - allok = 1; - -out: - if (devfd >= 0) - close(devfd); - if (bp) - free(bp); - if (inode != (ino_t) - 1) { - cleanupfileondev(argv[optind + 1], bootblkname, !allok || nowrite); - } - return (!allok); -} |
