Home | History | Annotate | Line # | Download | only in installboot
installboot.c revision 1.3.128.1
      1  1.3.128.1  yamt /*	$NetBSD: installboot.c,v 1.3.128.1 2008/05/18 12:32:27 yamt Exp $	*/
      2        1.1   wdk 
      3        1.1   wdk /*
      4        1.1   wdk  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5        1.1   wdk  * All rights reserved.
      6        1.1   wdk  *
      7        1.1   wdk  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1   wdk  * by Wayne Knowles
      9        1.1   wdk  *
     10        1.1   wdk  * Redistribution and use in source and binary forms, with or without
     11        1.1   wdk  * modification, are permitted provided that the following conditions
     12        1.1   wdk  * are met:
     13        1.1   wdk  * 1. Redistributions of source code must retain the above copyright
     14        1.1   wdk  *    notice, this list of conditions and the following disclaimer.
     15        1.1   wdk  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1   wdk  *    notice, this list of conditions and the following disclaimer in the
     17        1.1   wdk  *    documentation and/or other materials provided with the distribution.
     18        1.1   wdk  *
     19        1.1   wdk  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.1   wdk  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.1   wdk  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.1   wdk  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.1   wdk  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.1   wdk  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.1   wdk  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.1   wdk  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.1   wdk  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.1   wdk  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.1   wdk  * POSSIBILITY OF SUCH DAMAGE.
     30        1.1   wdk  */
     31        1.1   wdk 
     32        1.1   wdk #include <assert.h>
     33        1.1   wdk #include <err.h>
     34        1.1   wdk #include <fcntl.h>
     35        1.1   wdk #include <stdlib.h>
     36        1.1   wdk #include <stdio.h>
     37        1.1   wdk #include <string.h>
     38        1.1   wdk #include <unistd.h>
     39        1.1   wdk 
     40        1.1   wdk #include <sys/param.h>
     41        1.1   wdk #include <sys/stat.h>
     42        1.1   wdk #include <sys/disklabel.h>
     43        1.1   wdk 
     44        1.1   wdk 
     45        1.1   wdk #define	VERBOSE(msg)	if (verbose)				\
     46        1.1   wdk 				fprintf(stderr, msg)
     47        1.1   wdk #define	FATAL(a1,a2)	errx(EXIT_FAILURE, a1, a2)
     48        1.1   wdk #define	FATALIO(a1,a2)	err(EXIT_FAILURE, a1, a2)
     49        1.1   wdk 
     50        1.1   wdk #define BOOTBLOCK_NUMBER	2
     51        1.1   wdk #define	BOOTBLOCK_OFFSET	BOOTBLOCK_NUMBER*DEV_BSIZE
     52        1.1   wdk #define	DEFAULT_BOOTFILE	"boot"
     53        1.1   wdk 
     54        1.1   wdk static void	usage __P((void));
     55        1.1   wdk static void	do_list __P((const char *));
     56        1.1   wdk static void	do_remove __P((const char *, const char *));
     57        1.1   wdk static void	do_install __P((const char *, const char *, const char *));
     58        1.1   wdk static int	mipsvh_cksum __P((struct mips_volheader *));
     59        1.1   wdk static void	read_volheader __P((const char *, struct mips_volheader *));
     60        1.1   wdk static void	write_volheader __P((const char *, struct mips_volheader *));
     61        1.1   wdk static struct mips_voldir *voldir_findfile __P((struct mips_volheader *,
     62        1.1   wdk 						const char *, int));
     63        1.1   wdk 
     64        1.1   wdk int verbose, nowrite;
     65        1.1   wdk 
     66        1.1   wdk static void
     67        1.1   wdk usage()
     68        1.1   wdk {
     69        1.1   wdk 
     70        1.1   wdk 	fprintf(stderr, "usage:\n");
     71        1.2   cgd 	fprintf(stderr, "\t%s [-nv] disk bootstrap [name]\n", getprogname());
     72        1.2   cgd 	fprintf(stderr, "\t%s -r [-nv] disk [name]\n", getprogname());
     73        1.2   cgd 	fprintf(stderr, "\t%s -l [-nv] disk\n", getprogname());
     74        1.1   wdk 	exit(EXIT_FAILURE);
     75        1.1   wdk }
     76        1.1   wdk 
     77        1.1   wdk int
     78        1.1   wdk main(int argc, char *argv[])
     79        1.1   wdk {
     80        1.1   wdk 	const char *disk;
     81        1.1   wdk 	int c, rflag, lflag;
     82        1.1   wdk 
     83        1.1   wdk 	rflag = lflag = verbose = nowrite = 0;
     84        1.1   wdk 
     85        1.1   wdk 	while ((c = getopt(argc, argv, "lnrv")) != -1) {
     86        1.1   wdk 		switch (c) {
     87        1.1   wdk 		case 'l':
     88        1.1   wdk 			/* List volume directory contents */
     89        1.1   wdk 			lflag = 1;
     90        1.1   wdk 			break;
     91        1.1   wdk 		case 'n':
     92        1.1   wdk 			/* Disable write of boot sectors */
     93        1.1   wdk 			nowrite = 1;
     94        1.1   wdk 			break;
     95        1.1   wdk 		case 'r':
     96        1.1   wdk 			/* Clear any existing boot block */
     97        1.1   wdk 			rflag = 1;
     98        1.1   wdk 			break;
     99        1.1   wdk 		case 'v':
    100        1.1   wdk 			/* Verbose output */
    101        1.1   wdk 			verbose = 1;
    102        1.1   wdk 			break;
    103        1.1   wdk 		default:
    104        1.1   wdk 			usage();
    105        1.1   wdk 		}
    106        1.1   wdk 	}
    107        1.1   wdk 
    108        1.1   wdk 	argc -= optind;
    109        1.1   wdk 	argv += optind;
    110        1.1   wdk 
    111        1.1   wdk 	if ((lflag && rflag) || argc < 1 || (lflag && argc != 1) ||
    112        1.1   wdk 	    (rflag && argc > 3) || argc > 4)
    113        1.1   wdk 		usage();
    114        1.1   wdk 
    115        1.1   wdk 	disk = argv[0];
    116        1.1   wdk 
    117        1.1   wdk 	if (lflag)
    118        1.1   wdk 		do_list(disk);
    119        1.1   wdk 	else if (rflag)
    120        1.1   wdk 		do_remove(disk, argc==2?argv[1]:DEFAULT_BOOTFILE);
    121        1.1   wdk 	else
    122        1.1   wdk 		do_install(disk, argv[1], argc==3?argv[2]:DEFAULT_BOOTFILE);
    123        1.1   wdk 
    124        1.1   wdk 	exit(EXIT_SUCCESS);
    125        1.1   wdk }
    126        1.1   wdk 
    127        1.1   wdk static void
    128        1.1   wdk do_list(disk)
    129        1.1   wdk 	const char *disk;
    130        1.1   wdk {
    131        1.1   wdk 	struct mips_volheader vh;
    132        1.1   wdk 	struct mips_voldir *vdp;
    133        1.1   wdk 	int i;
    134        1.1   wdk 
    135        1.1   wdk 	read_volheader(disk, &vh);
    136        1.1   wdk 
    137        1.1   wdk 	printf("Slot\t  LBN\tLength\tFilename\n");
    138        1.1   wdk 	printf("------------------------------------------\n");
    139        1.1   wdk 	for (i=0, vdp=vh.vh_voldir; i<MIPS_NVOLDIR; i++, vdp++)
    140        1.1   wdk 		if (vdp->vd_len)
    141        1.1   wdk 			printf("%2d:\t%5d\t%6d\t%s\n", i, vdp->vd_lba,
    142        1.1   wdk 			       vdp->vd_len, vdp->vd_name);
    143        1.1   wdk }
    144        1.1   wdk 
    145        1.1   wdk static void
    146        1.1   wdk do_remove(disk, filename)
    147        1.1   wdk 	const char *disk;
    148        1.1   wdk 	const char *filename;
    149        1.1   wdk {
    150        1.1   wdk 	struct mips_volheader vh;
    151        1.1   wdk 	struct mips_voldir *vdp;
    152        1.1   wdk 
    153        1.1   wdk 	read_volheader(disk, &vh);
    154        1.1   wdk 	vdp = voldir_findfile(&vh, filename, 0);
    155        1.1   wdk 	if (vdp == NULL)
    156        1.1   wdk 		FATAL("%s: file not found", disk);
    157        1.1   wdk 
    158        1.3   wdk 	memset(vdp, 0, sizeof(*vdp));
    159        1.1   wdk 
    160        1.1   wdk 	/* Update volume header */
    161        1.1   wdk 	write_volheader(disk, &vh);
    162        1.1   wdk }
    163        1.1   wdk 
    164        1.1   wdk static void
    165        1.1   wdk do_install(disk, bootstrap, bootname)
    166        1.1   wdk 	const char *disk;
    167        1.1   wdk 	const char *bootstrap;
    168        1.1   wdk 	const char *bootname;
    169        1.1   wdk {
    170        1.1   wdk 	struct stat bootstrapsb;
    171        1.1   wdk 	struct mips_volheader vh;
    172        1.1   wdk 	struct mips_voldir *vdp;
    173        1.1   wdk 	int fd;
    174        1.1   wdk 	char *boot_code;
    175        1.1   wdk 	size_t boot_size;
    176        1.1   wdk 	ssize_t len;
    177        1.1   wdk 
    178        1.1   wdk 	/* Open the input file and check it out */
    179        1.1   wdk 	if ((fd = open(bootstrap, O_RDONLY)) == -1)
    180        1.1   wdk 		FATALIO("open %s", bootstrap);
    181        1.1   wdk 	if (fstat(fd, &bootstrapsb) == -1)
    182        1.1   wdk 		FATALIO("fstat %s", bootstrap);
    183        1.1   wdk 	if (!S_ISREG(bootstrapsb.st_mode))
    184        1.1   wdk 		FATAL("%s must be a regular file", bootstrap);
    185        1.1   wdk 
    186        1.1   wdk 	boot_size = roundup(bootstrapsb.st_size, DEV_BSIZE);
    187        1.1   wdk 
    188        1.1   wdk 	if (boot_size > 8192-1024)
    189        1.1   wdk 		FATAL("bootstrap program too large (%d bytes)", boot_size);
    190        1.1   wdk 
    191        1.1   wdk 	boot_code = malloc(boot_size);
    192        1.1   wdk 	if (boot_code == NULL)
    193        1.1   wdk 		FATAL("malloc %d bytes failed", boot_size);
    194        1.3   wdk 	memset(boot_code, 0, boot_size);
    195        1.1   wdk 
    196        1.1   wdk 	/* read the file into the buffer */
    197        1.1   wdk 	len = read(fd, boot_code, bootstrapsb.st_size);
    198        1.1   wdk 	if (len == -1)
    199        1.1   wdk 		FATALIO("read %s", bootstrap);
    200        1.1   wdk 	else if (len != bootstrapsb.st_size)
    201        1.1   wdk 		FATAL("read %s: short read", bootstrap);
    202        1.1   wdk 	(void)close(fd);
    203        1.1   wdk 
    204        1.1   wdk 	read_volheader(disk, &vh);
    205        1.1   wdk 
    206        1.1   wdk 	vdp = voldir_findfile(&vh, bootname, 1);
    207        1.1   wdk 	if (vdp == NULL)
    208        1.1   wdk 		FATAL("%s: volume directory full", disk);
    209        1.1   wdk 
    210        1.1   wdk 	strcpy(vdp->vd_name, bootname);
    211        1.1   wdk 	vdp->vd_lba = BOOTBLOCK_NUMBER;
    212        1.1   wdk 	vdp->vd_len = bootstrapsb.st_size;
    213        1.1   wdk 
    214        1.1   wdk 	if (nowrite) {
    215        1.1   wdk 	    if (verbose)
    216        1.1   wdk 		    fprintf(stderr, "not writing\n");
    217        1.1   wdk 	    return;
    218        1.1   wdk 	}
    219        1.1   wdk 
    220        1.1   wdk 	if (verbose)
    221        1.1   wdk 		fprintf(stderr, "writing bootstrap (%d bytes at logical block %d)\n",
    222        1.1   wdk 			boot_size, 2);
    223        1.1   wdk 
    224        1.1   wdk 	/* Write bootstrap */
    225        1.1   wdk 	if ((fd = open(disk, O_WRONLY)) == -1)
    226        1.1   wdk 		FATALIO("open %s", bootstrap);
    227        1.1   wdk 	len = pwrite(fd, boot_code, boot_size, BOOTBLOCK_OFFSET);
    228        1.1   wdk 	if (len == -1)
    229        1.1   wdk 		FATAL("write %s", disk);
    230        1.1   wdk 	if (len != boot_size)
    231        1.1   wdk 		FATAL("write %s: short write", disk);
    232        1.1   wdk 	(void) close(fd);
    233        1.1   wdk 
    234        1.1   wdk 	/* Update volume header */
    235        1.1   wdk 	write_volheader(disk, &vh);
    236        1.1   wdk }
    237        1.1   wdk 
    238        1.1   wdk static void
    239        1.1   wdk read_volheader(disk, vhp)
    240        1.1   wdk      const char *disk;
    241        1.1   wdk      struct mips_volheader *vhp;
    242        1.1   wdk {
    243        1.1   wdk 	int vfd;
    244        1.1   wdk 	ssize_t len;
    245        1.1   wdk 
    246        1.1   wdk 	if ((vfd = open(disk, O_RDONLY)) == -1)
    247        1.1   wdk 		FATALIO("open %s", disk);
    248        1.1   wdk 
    249        1.1   wdk 	len = pread(vfd, vhp, sizeof(*vhp), MIPS_VHSECTOR*DEV_BSIZE);
    250        1.1   wdk 
    251        1.1   wdk 	(void) close(vfd);
    252        1.1   wdk 
    253        1.1   wdk 	if (len == -1)
    254        1.1   wdk 		FATALIO("read %s", disk);
    255        1.1   wdk 	if (len != sizeof(*vhp))
    256        1.1   wdk 		FATAL("read %s: short read", disk);
    257        1.1   wdk 
    258        1.1   wdk 	/* Check volume header magic */
    259        1.1   wdk 	if (vhp->vh_magic != MIPS_VHMAGIC)
    260        1.1   wdk 		FATAL("%s: no volume header", disk);
    261        1.1   wdk 
    262        1.1   wdk 	/* check volume header checksum */
    263        1.1   wdk 	if (mipsvh_cksum(vhp))
    264        1.1   wdk 		FATAL("%s: volume header corrupted", disk);
    265        1.1   wdk }
    266        1.1   wdk 
    267        1.1   wdk static void
    268        1.1   wdk write_volheader(disk, vhp)
    269        1.1   wdk 	const char *disk;
    270        1.1   wdk 	struct mips_volheader *vhp;
    271        1.1   wdk {
    272        1.1   wdk 	int vfd;
    273        1.1   wdk 	ssize_t len;
    274        1.1   wdk 
    275        1.1   wdk 	/* update volume header checksum */
    276        1.1   wdk 	vhp->vh_cksum = 0;
    277        1.1   wdk 	vhp->vh_cksum = -mipsvh_cksum(vhp);
    278        1.1   wdk 
    279        1.1   wdk 	if ((vfd = open(disk, O_WRONLY)) == -1)
    280        1.1   wdk 		FATALIO("open %s", disk);
    281        1.1   wdk 
    282        1.1   wdk 	if (verbose)
    283        1.1   wdk 		fprintf(stderr, "%s: writing volume header\n", disk);
    284        1.1   wdk 
    285        1.1   wdk 	len = pwrite(vfd, vhp, sizeof(*vhp), MIPS_VHSECTOR*512); /* XXX */
    286        1.1   wdk 	if (len == -1)
    287        1.1   wdk 		FATALIO("write %s", disk);
    288        1.1   wdk 	if (len != sizeof(*vhp))
    289        1.1   wdk 		FATAL("write %s: short write", disk);
    290        1.1   wdk 
    291        1.1   wdk 	(void) close(vfd);
    292        1.1   wdk }
    293        1.1   wdk 
    294        1.1   wdk /*
    295        1.1   wdk  * Compute checksum for MIPS disk volume header
    296        1.1   wdk  *
    297        1.1   wdk  * Mips volume header checksum is the 32bit 2's complement sum
    298        1.1   wdk  * of the entire volume header structure
    299        1.1   wdk  */
    300        1.1   wdk int
    301        1.1   wdk mipsvh_cksum(vhp)
    302        1.1   wdk 	struct mips_volheader *vhp;
    303        1.1   wdk {
    304        1.1   wdk 	int i, *ptr;
    305        1.1   wdk 	int cksum = 0;
    306        1.1   wdk 
    307        1.1   wdk 	ptr = (int *)vhp;
    308        1.1   wdk 	i = sizeof(*vhp) / sizeof(*ptr);
    309        1.1   wdk 	while (i--)
    310        1.1   wdk 		cksum += *ptr++;
    311        1.1   wdk 	return cksum;
    312        1.1   wdk }
    313        1.1   wdk 
    314        1.1   wdk 
    315        1.1   wdk /*
    316        1.1   wdk  * Locate the volume directory slot that matches a filename
    317        1.1   wdk  *
    318        1.1   wdk  * If the file entry cannot be found and create is non-zero the next
    319        1.1   wdk  * empty slot is returned, otherwise return NULL
    320        1.1   wdk  */
    321        1.1   wdk static struct mips_voldir *
    322        1.1   wdk voldir_findfile(vhp, file, create)
    323        1.1   wdk 	struct mips_volheader *vhp;
    324        1.1   wdk 	const char *file;
    325        1.1   wdk 	int create;		/* return unused entry if not found */
    326        1.1   wdk {
    327        1.1   wdk 	struct mips_voldir *vdp = vhp->vh_voldir;
    328        1.1   wdk 	int i;
    329        1.1   wdk 
    330        1.1   wdk 	for (i=0; i<MIPS_NVOLDIR; i++, vdp++) {
    331        1.1   wdk 		if (strcmp(vdp->vd_name, file) == 0)
    332        1.1   wdk 			return vdp;
    333        1.1   wdk 	}
    334        1.1   wdk 	if (create) {
    335        1.1   wdk 		vdp = vhp->vh_voldir;
    336        1.1   wdk 		for (i=0; i<MIPS_NVOLDIR; i++, vdp++)
    337        1.1   wdk 			if (vdp->vd_len == 0)
    338        1.1   wdk 				return vdp;
    339        1.1   wdk 	}
    340        1.1   wdk 	return NULL;
    341        1.1   wdk }
    342