Home | History | Annotate | Line # | Download | only in inst
inst.c revision 1.22
      1  1.22  dholland /*	$NetBSD: inst.c,v 1.22 2016/06/11 06:20:11 dholland Exp $	*/
      2   1.1   thorpej 
      3   1.4   thorpej /*-
      4   1.4   thorpej  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
      5   1.1   thorpej  * All rights reserved.
      6   1.1   thorpej  *
      7   1.4   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8   1.4   thorpej  * by Jason R. Thorpe.
      9   1.4   thorpej  *
     10   1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     11   1.1   thorpej  * modification, are permitted provided that the following conditions
     12   1.1   thorpej  * are met:
     13   1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     14   1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     15   1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     17   1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     18   1.1   thorpej  *
     19   1.4   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.4   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.4   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.4   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.4   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.4   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.4   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.4   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.4   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.4   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.4   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     30   1.4   thorpej  */
     31   1.4   thorpej 
     32   1.4   thorpej /*
     33   1.1   thorpej  * Portions of this program are inspired by (and have borrowed code from)
     34   1.1   thorpej  * the `editlabel' program that accompanies NetBSD/vax, which carries
     35   1.1   thorpej  * the following notice:
     36   1.1   thorpej  *
     37   1.1   thorpej  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
     38   1.1   thorpej  * All rights reserved.
     39   1.1   thorpej  *
     40   1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     41   1.1   thorpej  * modification, are permitted provided that the following conditions
     42   1.1   thorpej  * are met:
     43   1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     44   1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     45   1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     46   1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     47   1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     48   1.1   thorpej  * 3. All advertising materials mentioning features or use of this software
     49   1.1   thorpej  *    must display the following acknowledgement:
     50   1.1   thorpej  *	This product includes software developed at Ludd, University of
     51   1.1   thorpej  *	Lule}, Sweden and its contributors.
     52   1.1   thorpej  * 4. The name of the author may not be used to endorse or promote products
     53   1.1   thorpej  *    derived from this software without specific prior written permission
     54   1.1   thorpej  *
     55   1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     56   1.1   thorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     57   1.1   thorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     58   1.1   thorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     59   1.1   thorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     60   1.1   thorpej  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     61   1.1   thorpej  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     62   1.1   thorpej  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     63   1.1   thorpej  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     64   1.1   thorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     65   1.1   thorpej  * SUCH DAMAGE.
     66   1.1   thorpej  */
     67   1.1   thorpej 
     68   1.1   thorpej #define DKTYPENAMES
     69   1.1   thorpej 
     70   1.1   thorpej #include <sys/param.h>
     71   1.1   thorpej #include <sys/reboot.h>
     72   1.1   thorpej #include <sys/disklabel.h>
     73   1.1   thorpej 
     74   1.1   thorpej #include <lib/libsa/stand.h>
     75  1.11   tsutsui #include <lib/libkern/libkern.h>
     76   1.1   thorpej 
     77   1.1   thorpej #include <hp300/stand/common/samachdep.h>
     78   1.1   thorpej 
     79   1.1   thorpej char line[100];
     80   1.1   thorpej 
     81   1.1   thorpej extern	u_int opendev;
     82   1.1   thorpej extern	char *lowram;
     83   1.1   thorpej extern	int noconsole;
     84   1.1   thorpej extern	int netio_ask;
     85   1.1   thorpej 
     86   1.1   thorpej char	*kernel_name = "/netbsd";
     87   1.1   thorpej 
     88  1.11   tsutsui void	main(void);
     89  1.11   tsutsui void	dsklabel(void);
     90  1.11   tsutsui void	miniroot(void);
     91  1.11   tsutsui void	bootmini(void);
     92  1.11   tsutsui void	resetsys(void);
     93  1.11   tsutsui void	gethelp(void);
     94  1.11   tsutsui int	opendisk(char *, char *, int, char, int *);
     95  1.11   tsutsui void	disklabel_edit(struct disklabel *);
     96  1.11   tsutsui void	disklabel_show(struct disklabel *);
     97  1.11   tsutsui int	disklabel_write(char *, int, struct open_file *);
     98  1.11   tsutsui void	get_fstype(struct disklabel *lp, int);
     99  1.11   tsutsui int	a2int(char *);
    100   1.1   thorpej 
    101   1.1   thorpej struct	inst_command {
    102   1.1   thorpej 	char	*ic_cmd;		/* command name */
    103   1.1   thorpej 	char	*ic_desc;		/* command description */
    104  1.16   tsutsui 	void	(*ic_func)(void);	/* handling function */
    105   1.1   thorpej } inst_commands[] = {
    106   1.1   thorpej 	{ "disklabel",	"place partition map on disk",	dsklabel },
    107   1.1   thorpej 	{ "miniroot",	"place miniroot on disk",	miniroot },
    108   1.1   thorpej 	{ "boot",	"boot from miniroot",		bootmini },
    109   1.1   thorpej 	{ "reset",	"reset the system",		resetsys },
    110   1.1   thorpej 	{ "help",	"display command list",		gethelp },
    111   1.1   thorpej };
    112   1.1   thorpej #define NCMDS	(sizeof(inst_commands) / sizeof(inst_commands[0]))
    113   1.1   thorpej 
    114  1.11   tsutsui void
    115  1.13   tsutsui main(void)
    116   1.1   thorpej {
    117  1.11   tsutsui 	int i;
    118   1.1   thorpej 
    119   1.1   thorpej 	/*
    120   1.1   thorpej 	 * We want netopen() to ask for IP address, etc, rather
    121   1.1   thorpej 	 * that using bootparams.
    122   1.1   thorpej 	 */
    123   1.1   thorpej 	netio_ask = 1;
    124   1.1   thorpej 
    125   1.1   thorpej 	printf("\n");
    126  1.18   tsutsui 	printf(">> %s, Revision %s (from NetBSD %s)\n",
    127  1.18   tsutsui 	    bootprog_name, bootprog_rev, bootprog_kernrev);
    128   1.3   thorpej 	printf(">> HP 9000/%s SPU\n", getmachineid());
    129   1.1   thorpej 	gethelp();
    130   1.1   thorpej 
    131   1.1   thorpej 	for (;;) {
    132   1.1   thorpej 		printf("sys_inst> ");
    133  1.11   tsutsui 		memset(line, 0, sizeof(line));
    134  1.22  dholland 		kgets(line, sizeof(line));
    135   1.1   thorpej 		if (line[0] == '\n' || line[0] == '\0')
    136   1.1   thorpej 			continue;
    137   1.1   thorpej 
    138   1.1   thorpej 		for (i = 0; i < NCMDS; ++i)
    139   1.1   thorpej 			if (strcmp(line, inst_commands[i].ic_cmd) == 0) {
    140   1.1   thorpej 				(*inst_commands[i].ic_func)();
    141   1.1   thorpej 				break;
    142   1.1   thorpej 			}
    143   1.1   thorpej 
    144   1.1   thorpej 
    145   1.1   thorpej 		if (i == NCMDS)
    146   1.1   thorpej 			printf("unknown command: %s\n", line);
    147   1.1   thorpej 	}
    148   1.1   thorpej }
    149   1.1   thorpej 
    150   1.1   thorpej void
    151  1.13   tsutsui gethelp(void)
    152   1.1   thorpej {
    153   1.1   thorpej 	int i;
    154   1.1   thorpej 
    155   1.1   thorpej 	printf(">> Available commands:\n");
    156   1.1   thorpej 	for (i = 0; i < NCMDS; ++i)
    157   1.1   thorpej 		printf(">>     %s - %s\n", inst_commands[i].ic_cmd,
    158   1.1   thorpej 		    inst_commands[i].ic_desc);
    159   1.1   thorpej }
    160   1.1   thorpej 
    161   1.1   thorpej /*
    162   1.1   thorpej  * Do all the steps necessary to place a disklabel on a disk.
    163   1.1   thorpej  * Note, this assumes 512 byte sectors.
    164   1.1   thorpej  */
    165   1.1   thorpej void
    166  1.13   tsutsui dsklabel(void)
    167   1.1   thorpej {
    168   1.1   thorpej 	struct disklabel *lp;
    169   1.1   thorpej 	struct open_file *disk_ofp;
    170   1.1   thorpej 	int dfd, error;
    171   1.1   thorpej 	size_t xfersize;
    172   1.1   thorpej 	char block[DEV_BSIZE], diskname[64];
    173   1.1   thorpej 	extern struct open_file files[];
    174   1.1   thorpej 
    175   1.8   thorpej 	printf(
    176   1.8   thorpej "You will be asked several questions about your disk, most of which\n"
    177   1.8   thorpej "require prior knowledge of the disk's geometry.  There is no easy way\n"
    178   1.8   thorpej "for the system to provide this information for you.  If you do not have\n"
    179   1.8   thorpej "this information, please consult your disk's manual or another\n"
    180   1.8   thorpej "informative source.\n\n");
    181   1.1   thorpej 
    182   1.1   thorpej 	/* Error message printed by opendisk() */
    183   1.1   thorpej 	if (opendisk("Disk to label?", diskname, sizeof(diskname),
    184   1.1   thorpej 	    ('a' + RAW_PART), &dfd))
    185   1.1   thorpej 		return;
    186   1.1   thorpej 
    187   1.1   thorpej 	disk_ofp = &files[dfd];
    188   1.1   thorpej 
    189  1.11   tsutsui 	memset(block, 0, sizeof(block));
    190  1.11   tsutsui 	if ((error = (*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
    191  1.11   tsutsui 	    F_READ, LABELSECTOR, sizeof(block), block, &xfersize)) != 0) {
    192   1.1   thorpej 		printf("cannot read disk %s, errno = %d\n", diskname, error);
    193   1.1   thorpej 		return;
    194   1.1   thorpej 	}
    195   1.1   thorpej 
    196  1.10       wiz 	printf("Successfully read %d bytes from %s\n", xfersize, diskname);
    197   1.1   thorpej 
    198   1.1   thorpej 	lp = (struct disklabel *)((void *)(&block[LABELOFFSET]));
    199   1.1   thorpej 
    200   1.1   thorpej  disklabel_loop:
    201  1.11   tsutsui 	memset(line, 0, sizeof(line));
    202   1.1   thorpej 	printf("(z)ap, (e)dit, (s)how, (w)rite, (d)one > ");
    203  1.22  dholland 	kgets(line, sizeof(line));
    204   1.1   thorpej 	if (line[0] == '\n' || line[0] == '\0')
    205   1.1   thorpej 		goto disklabel_loop;
    206   1.1   thorpej 
    207   1.1   thorpej 	switch (line[0]) {
    208   1.1   thorpej 	case 'z':
    209   1.1   thorpej 	case 'Z': {
    210   1.1   thorpej 		char zap[DEV_BSIZE];
    211  1.11   tsutsui 		memset(zap, 0, sizeof(zap));
    212   1.1   thorpej 		(void)(*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
    213   1.1   thorpej 		    F_WRITE, LABELSECTOR, sizeof(zap), zap, &xfersize);
    214   1.1   thorpej 		}
    215   1.1   thorpej 		goto out;
    216   1.1   thorpej 		/* NOTREACHED */
    217   1.1   thorpej 
    218   1.1   thorpej 	case 'e':
    219   1.1   thorpej 	case 'E':
    220   1.1   thorpej 		disklabel_edit(lp);
    221   1.1   thorpej 		break;
    222   1.1   thorpej 
    223   1.1   thorpej 	case 's':
    224   1.1   thorpej 	case 'S':
    225   1.1   thorpej 		disklabel_show(lp);
    226   1.1   thorpej 		break;
    227   1.1   thorpej 
    228   1.1   thorpej 	case 'w':
    229   1.1   thorpej 	case 'W':
    230   1.1   thorpej 		/*
    231   1.1   thorpej 		 * Error message will be displayed by disklabel_write()
    232   1.1   thorpej 		 */
    233   1.1   thorpej 		if (disklabel_write(block, sizeof(block), disk_ofp))
    234   1.1   thorpej 			goto out;
    235   1.1   thorpej 		else
    236  1.10       wiz 			printf("Successfully wrote label to %s\n", diskname);
    237   1.1   thorpej 		break;
    238   1.1   thorpej 
    239   1.1   thorpej 	case 'd':
    240   1.1   thorpej 	case 'D':
    241   1.1   thorpej 		goto out;
    242   1.1   thorpej 		/* NOTREACHED */
    243   1.1   thorpej 
    244   1.1   thorpej 	default:
    245   1.9       wiz 		printf("unknown command: %s\n", line);
    246   1.1   thorpej 	}
    247   1.1   thorpej 
    248   1.1   thorpej 	goto disklabel_loop;
    249   1.1   thorpej 	/* NOTREACHED */
    250   1.1   thorpej 
    251   1.1   thorpej  out:
    252   1.1   thorpej 	/*
    253   1.1   thorpej 	 * Close disk.  Marks disk `not alive' so that partition
    254   1.1   thorpej 	 * information will be reloaded upon next open.
    255   1.1   thorpej 	 */
    256   1.1   thorpej 	(void)close(dfd);
    257   1.1   thorpej }
    258   1.1   thorpej 
    259   1.1   thorpej #define GETNUM(out, num)						\
    260   1.1   thorpej 	printf((out), (num));						\
    261  1.11   tsutsui 	memset(line, 0, sizeof(line));					\
    262  1.22  dholland 	kgets(line, sizeof(line));							\
    263   1.1   thorpej 	if (line[0])							\
    264   1.1   thorpej 		(num) = atoi(line);
    265   1.1   thorpej 
    266   1.1   thorpej #define GETNUM2(out, num1, num2)					\
    267   1.1   thorpej 	printf((out), (num1), (num2));					\
    268  1.11   tsutsui 	memset(line, 0, sizeof(line));					\
    269  1.22  dholland 	kgets(line, sizeof(line));							\
    270   1.1   thorpej 	if (line[0])							\
    271   1.1   thorpej 		(num2) = atoi(line);
    272   1.1   thorpej 
    273   1.1   thorpej #define GETSTR(out, str)						\
    274   1.1   thorpej 	printf((out), (str));						\
    275  1.11   tsutsui 	memset(line, 0, sizeof(line));					\
    276  1.22  dholland 	kgets(line, sizeof(line));							\
    277   1.1   thorpej 	if (line[0])							\
    278   1.1   thorpej 		strcpy((str), line);
    279   1.1   thorpej 
    280   1.1   thorpej #define FLAGS(out, flag)						\
    281   1.1   thorpej 	printf((out), lp->d_flags & (flag) ? 'y' : 'n');		\
    282  1.11   tsutsui 	memset(line, 0, sizeof(line));					\
    283  1.22  dholland 	kgets(line, sizeof(line));							\
    284   1.1   thorpej 	if (line[0] == 'y' || line[0] == 'Y')				\
    285   1.1   thorpej 		lp->d_flags |= (flag);					\
    286   1.1   thorpej 	else								\
    287   1.1   thorpej 		lp->d_flags &= ~(flag);
    288   1.1   thorpej 
    289   1.5   thorpej struct fsname_to_type {
    290   1.5   thorpej 	const char *name;
    291  1.12   tsutsui 	uint8_t type;
    292   1.5   thorpej } n_to_t[] = {
    293   1.5   thorpej 	{ "unused",	FS_UNUSED },
    294   1.5   thorpej 	{ "ffs",	FS_BSDFFS },
    295   1.5   thorpej 	{ "swap",	FS_SWAP },
    296   1.5   thorpej 	{ "boot",	FS_BOOT },
    297   1.5   thorpej 	{ NULL,		0 },
    298   1.5   thorpej };
    299   1.5   thorpej 
    300   1.5   thorpej void
    301  1.13   tsutsui get_fstype(struct disklabel *lp, int partno)
    302   1.5   thorpej {
    303   1.5   thorpej 	static int blocksize = 8192;	/* XXX */
    304   1.5   thorpej 	struct partition *pp = &lp->d_partitions[partno];
    305   1.5   thorpej 	struct fsname_to_type *np;
    306   1.5   thorpej 	int fragsize;
    307   1.5   thorpej 	char line[80], str[80];
    308   1.5   thorpej 
    309   1.5   thorpej 	if (pp->p_size == 0) {
    310   1.5   thorpej 		/*
    311   1.5   thorpej 		 * No need to bother asking for a zero-sized partition.
    312   1.5   thorpej 		 */
    313   1.5   thorpej 		pp->p_fstype = FS_UNUSED;
    314   1.5   thorpej 		return;
    315   1.5   thorpej 	}
    316   1.5   thorpej 
    317   1.5   thorpej 	/*
    318   1.5   thorpej 	 * Select a default.
    319   1.5   thorpej 	 * XXX Should we check what might be in the label already?
    320   1.5   thorpej 	 */
    321   1.5   thorpej 	if (partno == 1)
    322   1.5   thorpej 		strcpy(str, "swap");
    323   1.5   thorpej 	else if (partno == RAW_PART)
    324   1.5   thorpej 		strcpy(str, "boot");
    325   1.5   thorpej 	else
    326   1.5   thorpej 		strcpy(str, "ffs");
    327   1.5   thorpej 
    328   1.5   thorpej  again:
    329   1.5   thorpej 	GETSTR("             fstype? [%s] ", str);
    330   1.5   thorpej 
    331   1.5   thorpej 	for (np = n_to_t; np->name != NULL; np++)
    332   1.5   thorpej 		if (strcmp(str, np->name) == 0)
    333   1.5   thorpej 			break;
    334   1.5   thorpej 
    335   1.5   thorpej 	if (np->name == NULL) {
    336   1.5   thorpej 		printf("Please use one of: ");
    337   1.5   thorpej 		for (np = n_to_t; np->name != NULL; np++)
    338   1.5   thorpej 			printf(" %s", np->name);
    339   1.5   thorpej 		printf(".\n");
    340   1.5   thorpej 		goto again;
    341   1.5   thorpej 	}
    342   1.5   thorpej 
    343   1.5   thorpej 	pp->p_fstype = np->type;
    344   1.5   thorpej 
    345   1.5   thorpej 	if (pp->p_fstype != FS_BSDFFS)
    346   1.5   thorpej 		return;
    347   1.5   thorpej 
    348   1.5   thorpej 	/*
    349   1.5   thorpej 	 * Get additional information needed for FFS.
    350   1.5   thorpej 	 */
    351   1.5   thorpej  ffs_again:
    352   1.5   thorpej 	GETNUM("             FFS block size? [%d] ", blocksize);
    353   1.5   thorpej 	if (blocksize < NBPG || (blocksize % NBPG) != 0) {
    354   1.5   thorpej 		printf("FFS block size must be a multiple of %d.\n", NBPG);
    355   1.5   thorpej 		goto ffs_again;
    356   1.5   thorpej 	}
    357   1.5   thorpej 
    358   1.5   thorpej 	fragsize = blocksize / 8;	/* XXX */
    359   1.5   thorpej 	fragsize = max(fragsize, lp->d_secsize);
    360   1.5   thorpej 	GETNUM("             FFS fragment size? [%d] ", fragsize);
    361   1.5   thorpej 	if (fragsize < lp->d_secsize || (fragsize % lp->d_secsize) != 0) {
    362   1.5   thorpej 		printf("FFS fragment size must be a multiple of sector size"
    363   1.5   thorpej 		    " (%d).\n", lp->d_secsize);
    364   1.5   thorpej 		goto ffs_again;
    365   1.5   thorpej 	}
    366   1.5   thorpej 	if ((blocksize % fragsize) != 0) {
    367   1.5   thorpej 		printf("FFS fragment size must be an even divisor of FFS"
    368   1.5   thorpej 		    " block size (%d).\n", blocksize);
    369   1.5   thorpej 		goto ffs_again;
    370   1.5   thorpej 	}
    371   1.5   thorpej 
    372   1.5   thorpej 	/*
    373   1.5   thorpej 	 * XXX Better sanity checking?
    374   1.5   thorpej 	 */
    375   1.5   thorpej 
    376   1.5   thorpej 	pp->p_frag = blocksize / fragsize;
    377   1.5   thorpej 	pp->p_fsize = fragsize;
    378   1.5   thorpej }
    379   1.5   thorpej 
    380   1.1   thorpej void
    381  1.13   tsutsui disklabel_edit(struct disklabel *lp)
    382   1.1   thorpej {
    383   1.1   thorpej 	int i;
    384   1.1   thorpej 
    385   1.1   thorpej 	printf("Select disk type.  Valid types:\n");
    386   1.1   thorpej 	for (i = 0; i < DKMAXTYPES; i++)
    387   1.1   thorpej 		printf("%d     %s\n", i, dktypenames[i]);
    388   1.1   thorpej 	printf("\n");
    389   1.1   thorpej 
    390   1.1   thorpej 	GETNUM("Disk type (number)? [%d] ", lp->d_type);
    391   1.1   thorpej 	GETSTR("Disk model name? [%s] ", lp->d_typename);
    392   1.1   thorpej 	GETSTR("Disk pack name? [%s] ", lp->d_packname);
    393   1.1   thorpej 	FLAGS("Bad sectoring? [%c] ", D_BADSECT);
    394   1.1   thorpej 	FLAGS("Ecc? [%c] ", D_ECC);
    395   1.1   thorpej 	FLAGS("Removable? [%c] ", D_REMOVABLE);
    396   1.1   thorpej 
    397   1.1   thorpej 	printf("\n");
    398   1.1   thorpej 
    399   1.1   thorpej 	GETNUM("Interleave? [%d] ", lp->d_interleave);
    400   1.1   thorpej 	GETNUM("Rpm? [%d] ", lp->d_rpm);
    401   1.1   thorpej 	GETNUM("Trackskew? [%d] ", lp->d_trackskew);
    402   1.1   thorpej 	GETNUM("Cylinderskew? [%d] ", lp->d_cylskew);
    403   1.1   thorpej 	GETNUM("Headswitch? [%d] ", lp->d_headswitch);
    404   1.1   thorpej 	GETNUM("Track-to-track? [%d] ", lp->d_trkseek);
    405   1.1   thorpej 	GETNUM("Drivedata 0? [%d] ", lp->d_drivedata[0]);
    406   1.1   thorpej 	GETNUM("Drivedata 1? [%d] ", lp->d_drivedata[1]);
    407   1.1   thorpej 	GETNUM("Drivedata 2? [%d] ", lp->d_drivedata[2]);
    408   1.1   thorpej 	GETNUM("Drivedata 3? [%d] ", lp->d_drivedata[3]);
    409   1.1   thorpej 	GETNUM("Drivedata 4? [%d] ", lp->d_drivedata[4]);
    410   1.1   thorpej 
    411   1.1   thorpej 	printf("\n");
    412   1.1   thorpej 
    413   1.1   thorpej 	GETNUM("Bytes/sector? [%d] ", lp->d_secsize);
    414   1.1   thorpej 	GETNUM("Sectors/track? [%d] ", lp->d_nsectors);
    415   1.1   thorpej 	GETNUM("Tracks/cylinder? [%d] ", lp->d_ntracks);
    416   1.6    scottr 	if (lp->d_secpercyl == 0)
    417   1.6    scottr 		lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
    418   1.1   thorpej 	GETNUM("Sectors/cylinder? [%d] ", lp->d_secpercyl);
    419   1.1   thorpej 	GETNUM("Cylinders? [%d] ", lp->d_ncylinders);
    420   1.6    scottr 	if (lp->d_secperunit == 0)
    421   1.6    scottr 		lp->d_secperunit = lp->d_ncylinders * lp->d_secpercyl;
    422   1.6    scottr 	GETNUM("Total sectors? [%d] ", lp->d_secperunit);
    423   1.1   thorpej 
    424   1.8   thorpej 	printf(
    425   1.8   thorpej "Enter partition table.  Note, sizes and offsets are in sectors.\n\n");
    426   1.1   thorpej 
    427   1.1   thorpej 	lp->d_npartitions = MAXPARTITIONS;
    428   1.1   thorpej 	for (i = 0; i < lp->d_npartitions; ++i) {
    429   1.1   thorpej 		GETNUM2("%c partition: offset? [%d] ", ('a' + i),
    430   1.1   thorpej 		    lp->d_partitions[i].p_offset);
    431   1.1   thorpej 		GETNUM("             size? [%d] ", lp->d_partitions[i].p_size);
    432   1.5   thorpej 		get_fstype(lp, i);
    433   1.1   thorpej 	}
    434   1.1   thorpej 
    435   1.1   thorpej 	/* Perform magic. */
    436   1.1   thorpej 	lp->d_magic = lp->d_magic2 = DISKMAGIC;
    437   1.1   thorpej 
    438   1.1   thorpej 	/* Calculate disklabel checksum. */
    439   1.1   thorpej 	lp->d_checksum = 0;
    440   1.1   thorpej 	lp->d_checksum = dkcksum(lp);
    441   1.1   thorpej }
    442   1.1   thorpej 
    443   1.1   thorpej void
    444  1.13   tsutsui disklabel_show(struct disklabel *lp)
    445   1.1   thorpej {
    446  1.11   tsutsui 	int i;
    447   1.1   thorpej 	struct partition *pp;
    448   1.1   thorpej 
    449   1.1   thorpej 	/*
    450   1.1   thorpej 	 * Check for valid disklabel.
    451   1.1   thorpej 	 */
    452   1.1   thorpej 	if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC) {
    453   1.1   thorpej 		printf("No disklabel to show.\n");
    454   1.1   thorpej 		return;
    455   1.1   thorpej 	}
    456   1.1   thorpej 
    457   1.1   thorpej 	if (lp->d_npartitions > MAXPARTITIONS || dkcksum(lp) != 0) {
    458   1.1   thorpej 		printf("Corrupted disklabel.\n");
    459   1.1   thorpej 		return;
    460   1.1   thorpej 	}
    461   1.1   thorpej 
    462   1.1   thorpej 	printf("\ndisk type %d (%s), %s: %s%s%s\n", lp->d_type,
    463   1.1   thorpej 	    lp->d_type < DKMAXTYPES ? dktypenames[lp->d_type] :
    464   1.1   thorpej 	    dktypenames[0], lp->d_typename,
    465   1.1   thorpej 	    (lp->d_flags & D_REMOVABLE) ? " removable" : "",
    466   1.1   thorpej 	    (lp->d_flags & D_ECC) ? " ecc" : "",
    467   1.1   thorpej 	    (lp->d_flags & D_BADSECT) ? " badsect" : "");
    468   1.1   thorpej 
    469   1.1   thorpej 	printf("interleave %d, rpm %d, trackskew %d, cylinderskew %d\n",
    470   1.1   thorpej 	    lp->d_interleave, lp->d_rpm, lp->d_trackskew, lp->d_cylskew);
    471   1.1   thorpej 
    472   1.1   thorpej 	printf("headswitch %d, track-to-track %d, drivedata: %d %d %d %d %d\n",
    473   1.1   thorpej 	    lp->d_headswitch, lp->d_trkseek, lp->d_drivedata[0],
    474   1.1   thorpej 	    lp->d_drivedata[1], lp->d_drivedata[2], lp->d_drivedata[3],
    475   1.1   thorpej 	    lp->d_drivedata[4]);
    476   1.1   thorpej 
    477   1.1   thorpej 	printf("\nbytes/sector: %d\n", lp->d_secsize);
    478   1.1   thorpej 	printf("sectors/track: %d\n", lp->d_nsectors);
    479   1.1   thorpej 	printf("tracks/cylinder: %d\n", lp->d_ntracks);
    480   1.1   thorpej 	printf("sectors/cylinder: %d\n", lp->d_secpercyl);
    481   1.1   thorpej 	printf("cylinders: %d\n", lp->d_ncylinders);
    482   1.6    scottr 	printf("total sectors: %d\n", lp->d_secperunit);
    483   1.1   thorpej 
    484   1.1   thorpej 	printf("\n%d partitions:\n", lp->d_npartitions);
    485   1.1   thorpej 	printf("     size   offset\n");
    486   1.1   thorpej 	pp = lp->d_partitions;
    487   1.1   thorpej 	for (i = 0; i < lp->d_npartitions; i++) {
    488  1.19   tsutsui 		printf("%c:   %d,    %d\n", 'a' + i, pp[i].p_size,
    489  1.19   tsutsui 		    pp[i].p_offset);
    490   1.1   thorpej 	}
    491   1.1   thorpej 	printf("\n");
    492   1.1   thorpej }
    493   1.1   thorpej 
    494   1.1   thorpej int
    495  1.13   tsutsui disklabel_write(char *block, int len, struct open_file *ofp)
    496   1.1   thorpej {
    497   1.1   thorpej 	int error = 0;
    498   1.1   thorpej 	size_t xfersize;
    499   1.1   thorpej 
    500  1.11   tsutsui 	if ((error = (*ofp->f_dev->dv_strategy)(ofp->f_devdata, F_WRITE,
    501  1.11   tsutsui 	    LABELSECTOR, len, block, &xfersize)) != 0)
    502   1.1   thorpej 		printf("cannot write disklabel, errno = %d\n", error);
    503   1.1   thorpej 
    504   1.1   thorpej 	return (error);
    505   1.1   thorpej }
    506   1.1   thorpej 
    507   1.1   thorpej int
    508  1.13   tsutsui opendisk(char *question, char *diskname, int len, char partition, int *fdp)
    509   1.1   thorpej {
    510  1.11   tsutsui 	char fulldiskname[64];
    511  1.11   tsutsui 	int i;
    512   1.1   thorpej 
    513   1.1   thorpej  getdiskname:
    514   1.1   thorpej 	printf("%s ", question);
    515  1.11   tsutsui 	memset(diskname, 0, len);
    516  1.11   tsutsui 	memset(fulldiskname, 0, sizeof(fulldiskname));
    517  1.22  dholland 	kgets(diskname, sizeof(diskname));
    518   1.1   thorpej 	if (diskname[0] == '\n' || diskname[0] == '\0')
    519   1.1   thorpej 		goto getdiskname;
    520   1.1   thorpej 
    521   1.1   thorpej 	/*
    522   1.1   thorpej 	 * devopen() is picky.  Make sure it gets the sort of string it
    523   1.1   thorpej 	 * wants.
    524   1.1   thorpej 	 */
    525  1.11   tsutsui 	memcpy(fulldiskname, diskname,
    526   1.1   thorpej 	    len < sizeof(fulldiskname) ? len : sizeof(fulldiskname));
    527   1.1   thorpej 	for (i = 0; fulldiskname[i + 1] != '\0'; ++i)
    528   1.1   thorpej 		/* Nothing. */ ;
    529   1.1   thorpej 	if (fulldiskname[i] < '0' || fulldiskname[i] > '9') {
    530   1.1   thorpej 		printf("invalid disk name %s\n", diskname);
    531   1.1   thorpej 		goto getdiskname;
    532   1.1   thorpej 	}
    533   1.1   thorpej 	fulldiskname[++i] = partition; fulldiskname[++i] = ':';
    534   1.1   thorpej 
    535   1.1   thorpej 	/*
    536   1.1   thorpej 	 * We always open for writing.
    537   1.1   thorpej 	 */
    538   1.1   thorpej 	if ((*fdp = open(fulldiskname, 1)) < 0) {
    539   1.1   thorpej 		printf("cannot open %s\n", diskname);
    540  1.11   tsutsui 		return 1;
    541   1.1   thorpej 	}
    542   1.1   thorpej 
    543  1.11   tsutsui 	return 0;
    544   1.1   thorpej }
    545   1.1   thorpej 
    546   1.1   thorpej /*
    547   1.1   thorpej  * Copy a miniroot image from an NFS server or tape to the `b' partition
    548   1.1   thorpej  * of the specified disk.  Note, this assumes 512 byte sectors.
    549   1.1   thorpej  */
    550   1.1   thorpej void
    551  1.13   tsutsui miniroot(void)
    552   1.1   thorpej {
    553   1.1   thorpej 	int sfd, dfd, i, nblks;
    554   1.1   thorpej 	char diskname[64], minirootname[128];
    555   1.1   thorpej 	char block[DEV_BSIZE];
    556   1.1   thorpej 	char tapename[64];
    557   1.2   thorpej 	int fileno, ignoreshread, eof, len;
    558   1.1   thorpej 	struct stat st;
    559   1.1   thorpej 	size_t xfersize;
    560   1.1   thorpej 	struct open_file *disk_ofp;
    561   1.1   thorpej 	extern struct open_file files[];
    562   1.1   thorpej 
    563   1.1   thorpej 	/* Error message printed by opendisk() */
    564   1.1   thorpej 	if (opendisk("Disk for miniroot?", diskname, sizeof(diskname),
    565   1.1   thorpej 	    'b', &dfd))
    566   1.1   thorpej 		return;
    567   1.1   thorpej 
    568   1.1   thorpej 	disk_ofp = &files[dfd];
    569   1.1   thorpej 
    570   1.1   thorpej  getsource:
    571   1.1   thorpej 	printf("Source? (N)FS, (t)ape, (d)one > ");
    572  1.11   tsutsui 	memset(line, 0, sizeof(line));
    573  1.22  dholland 	kgets(line, sizeof(line));
    574   1.1   thorpej 	if (line[0] == '\0')
    575   1.1   thorpej 		goto getsource;
    576   1.1   thorpej 
    577   1.1   thorpej 	switch (line[0]) {
    578   1.1   thorpej 	case 'n':
    579   1.1   thorpej 	case 'N':
    580   1.1   thorpej  name_of_nfs_miniroot:
    581   1.1   thorpej 		printf("Name of miniroot file? ");
    582  1.11   tsutsui 		memset(line, 0, sizeof(line));
    583  1.11   tsutsui 		memset(minirootname, 0, sizeof(minirootname));
    584  1.22  dholland 		kgets(line, sizeof(line));
    585   1.1   thorpej 		if (line[0] == '\0')
    586   1.1   thorpej 			goto name_of_nfs_miniroot;
    587   1.1   thorpej 		(void)strcat(minirootname, "le0a:");
    588   1.1   thorpej 		(void)strcat(minirootname, line);
    589   1.1   thorpej 		if ((sfd = open(minirootname, 0)) < 0) {
    590   1.1   thorpej 			printf("can't open %s\n", line);
    591   1.1   thorpej 			return;
    592   1.1   thorpej 		}
    593   1.1   thorpej 
    594   1.1   thorpej 		/*
    595   1.2   thorpej 		 * Find out how big the miniroot is... we can't
    596   1.2   thorpej 		 * check for size because it may be compressed.
    597   1.1   thorpej 		 */
    598   1.2   thorpej 		ignoreshread = 1;
    599   1.1   thorpej 		if (fstat(sfd, &st) < 0) {
    600   1.1   thorpej 			printf("can't stat %s\n", line);
    601   1.1   thorpej 			goto done;
    602   1.1   thorpej 		}
    603   1.1   thorpej 		nblks = (int)(st.st_size / sizeof(block));
    604   1.1   thorpej 
    605   1.2   thorpej 		printf("Copying miniroot from %s to %s...", line,
    606   1.1   thorpej 		    diskname);
    607   1.1   thorpej 		break;
    608   1.1   thorpej 
    609   1.1   thorpej 	case 't':
    610   1.1   thorpej 	case 'T':
    611   1.1   thorpej  name_of_tape_miniroot:
    612   1.1   thorpej 		printf("Which tape device? ");
    613  1.11   tsutsui 		memset(line, 0, sizeof(line));
    614  1.11   tsutsui 		memset(minirootname, 0, sizeof(minirootname));
    615  1.11   tsutsui 		memset(tapename, 0, sizeof(tapename));
    616  1.22  dholland 		kgets(line, sizeof(line));
    617   1.1   thorpej 		if (line[0] == '\0')
    618   1.1   thorpej 			goto name_of_tape_miniroot;
    619   1.1   thorpej 		strcat(minirootname, line);
    620   1.1   thorpej 		strcat(tapename, line);
    621   1.1   thorpej 
    622   1.1   thorpej 		printf("File number (first == 1)? ");
    623  1.11   tsutsui 		memset(line, 0, sizeof(line));
    624  1.22  dholland 		kgets(line, sizeof(line));
    625   1.1   thorpej 		fileno = a2int(line);
    626   1.1   thorpej 		if (fileno < 1 || fileno > 8) {
    627   1.1   thorpej 			printf("Invalid file number: %s\n", line);
    628   1.1   thorpej 			goto getsource;
    629   1.1   thorpej 		}
    630   1.1   thorpej 		for (i = 0; i < sizeof(minirootname); ++i) {
    631   1.1   thorpej 			if (minirootname[i] == '\0')
    632   1.1   thorpej 				break;
    633   1.1   thorpej 		}
    634   1.1   thorpej 		if (i == sizeof(minirootname) ||
    635   1.1   thorpej 		    (sizeof(minirootname) - i) < 8) {
    636   1.1   thorpej 			printf("Invalid device name: %s\n", tapename);
    637   1.1   thorpej 			goto getsource;
    638   1.1   thorpej 		}
    639   1.1   thorpej 		minirootname[i++] = 'a' + (fileno - 1);
    640   1.1   thorpej 		minirootname[i++] = ':';
    641   1.1   thorpej 		strcat(minirootname, "XXX");	/* lameness in open() */
    642   1.1   thorpej 
    643   1.2   thorpej 		ignoreshread = 0;
    644   1.1   thorpej 		printf("Copy how many %d byte blocks? ", DEV_BSIZE);
    645  1.11   tsutsui 		memset(line, 0, sizeof(line));
    646  1.22  dholland 		kgets(line, sizeof(line));
    647   1.1   thorpej 		nblks = a2int(line);
    648   1.1   thorpej 		if (nblks < 0) {
    649   1.1   thorpej 			printf("Invalid block count: %s\n", line);
    650   1.1   thorpej 			goto getsource;
    651   1.1   thorpej 		} else if (nblks == 0) {
    652   1.1   thorpej 			printf("Zero blocks?  Ok, aborting.\n");
    653   1.1   thorpej 			return;
    654   1.1   thorpej 		}
    655   1.1   thorpej 
    656   1.1   thorpej 		if ((sfd = open(minirootname, 0)) < 0) {
    657   1.1   thorpej 			printf("can't open %s file %c\n", tapename, fileno);
    658   1.1   thorpej 			return;
    659   1.1   thorpej 		}
    660   1.1   thorpej 
    661   1.2   thorpej 		printf("Copying %s file %d to %s...", tapename, fileno,
    662   1.1   thorpej 		    diskname);
    663   1.1   thorpej 		break;
    664   1.1   thorpej 
    665   1.1   thorpej 	case 'd':
    666   1.1   thorpej 	case 'D':
    667   1.1   thorpej 		return;
    668   1.1   thorpej 
    669   1.1   thorpej 	default:
    670   1.1   thorpej 		printf("Unknown source: %s\n", line);
    671   1.1   thorpej 		goto getsource;
    672   1.1   thorpej 	}
    673   1.1   thorpej 
    674   1.1   thorpej 	/*
    675   1.1   thorpej 	 * Copy loop...
    676   1.1   thorpej 	 * This is fairly slow... if someone wants to speed it
    677   1.1   thorpej 	 * up, they'll get no complaints from me.
    678   1.1   thorpej 	 */
    679   1.2   thorpej 	for (i = 0, eof = 0; i < nblks || ignoreshread == 0; i++) {
    680   1.2   thorpej 		if ((len = read(sfd, block, sizeof(block))) < 0) {
    681   1.2   thorpej 			printf("Read error, errno = %d\n", errno);
    682   1.2   thorpej 			goto out;
    683   1.2   thorpej 		}
    684   1.2   thorpej 
    685   1.2   thorpej 		/*
    686   1.2   thorpej 		 * Check for end-of-file.
    687   1.2   thorpej 		 */
    688   1.2   thorpej 		if (len == 0)
    689   1.1   thorpej 			goto done;
    690   1.2   thorpej 		else if (len < sizeof(block))
    691   1.2   thorpej 			eof = 1;
    692   1.2   thorpej 
    693   1.1   thorpej 		if ((*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
    694   1.2   thorpej 		    F_WRITE, i, len, block, &xfersize) || xfersize != len) {
    695   1.1   thorpej 			printf("Bad write at block %d, errno = %d\n",
    696   1.1   thorpej 			    i, errno);
    697   1.2   thorpej 			goto out;
    698   1.2   thorpej 		}
    699   1.2   thorpej 
    700   1.2   thorpej 		if (eof)
    701   1.1   thorpej 			goto done;
    702   1.1   thorpej 	}
    703   1.2   thorpej  done:
    704   1.1   thorpej 	printf("done\n");
    705   1.1   thorpej 
    706   1.1   thorpej 	printf("Successfully copied miniroot image.\n");
    707   1.1   thorpej 
    708   1.2   thorpej  out:
    709   1.1   thorpej 	close(sfd);
    710   1.1   thorpej 	close(dfd);
    711   1.1   thorpej }
    712   1.1   thorpej 
    713   1.1   thorpej /*
    714   1.1   thorpej  * Boot the kernel from the miniroot image into single-user.
    715   1.1   thorpej  */
    716   1.1   thorpej void
    717  1.13   tsutsui bootmini(void)
    718   1.1   thorpej {
    719   1.1   thorpej 	char diskname[64], bootname[64];
    720   1.1   thorpej 	int i;
    721   1.1   thorpej 
    722   1.1   thorpej  getdiskname:
    723   1.1   thorpej 	printf("Disk to boot from? ");
    724  1.11   tsutsui 	memset(diskname, 0, sizeof(diskname));
    725  1.11   tsutsui 	memset(bootname, 0, sizeof(bootname));
    726  1.22  dholland 	kgets(diskname, sizeof(diskname));
    727   1.1   thorpej 	if (diskname[0] == '\n' || diskname[0] == '\0')
    728   1.1   thorpej 		goto getdiskname;
    729   1.1   thorpej 
    730   1.1   thorpej 	/*
    731   1.1   thorpej 	 * devopen() is picky.  Make sure it gets the sort of string it
    732   1.1   thorpej 	 * wants.
    733   1.1   thorpej 	 */
    734   1.1   thorpej 	(void)strcat(bootname, diskname);
    735   1.1   thorpej 	for (i = 0; bootname[i + 1] != '\0'; ++i)
    736   1.1   thorpej 		/* Nothing. */ ;
    737   1.1   thorpej 	if (bootname[i] < '0' || bootname[i] > '9') {
    738   1.1   thorpej 		printf("invalid disk name %s\n", diskname);
    739   1.1   thorpej 		goto getdiskname;
    740   1.1   thorpej 	}
    741   1.1   thorpej 	bootname[++i] = 'b'; bootname[++i] = ':';
    742   1.1   thorpej 	(void)strcat(bootname, kernel_name);
    743   1.1   thorpej 
    744   1.1   thorpej 	howto = RB_SINGLE;	/* _Always_ */
    745   1.1   thorpej 
    746   1.1   thorpej 	printf("booting: %s -s\n", bootname);
    747   1.7  gmcgarry 	exec_hp300(bootname, (u_long)lowram, howto);
    748   1.1   thorpej 	printf("boot: %s\n", strerror(errno));
    749   1.1   thorpej }
    750   1.1   thorpej 
    751   1.1   thorpej /*
    752   1.1   thorpej  * Reset the system.
    753   1.1   thorpej  */
    754   1.1   thorpej void
    755  1.13   tsutsui resetsys(void)
    756   1.1   thorpej {
    757   1.1   thorpej 
    758   1.1   thorpej 	call_req_reboot();
    759   1.1   thorpej 	printf("panic: can't reboot, halting\n");
    760  1.15     perry 	__asm("stop #0x2700");
    761   1.1   thorpej }
    762   1.1   thorpej 
    763   1.1   thorpej int
    764  1.13   tsutsui a2int(char *cp)
    765   1.1   thorpej {
    766   1.1   thorpej 	if (*cp == '\0')
    767  1.20     isaki 		return -1;
    768   1.1   thorpej 
    769  1.20     isaki 	return atoi(cp);
    770   1.1   thorpej }
    771