rework setroot() and friends, largely by cloning from the sparc code
and whacking a bit here and there where appropriate. Does not yet do automatic root device detection, but that's much easier to add now. RB_ASKNAME now supports specification of network devices, for diskless booting. Also, RB_ASKNAME is now supported on _all_ kernels.
This commit is contained in:
parent
ba53a90965
commit
811bbb5c72
|
@ -1,30 +1,47 @@
|
|||
/* $NetBSD: autoconf.c,v 1.3 1996/04/12 06:07:05 cgd Exp $ */
|
||||
/* $NetBSD: autoconf.c,v 1.4 1996/06/12 01:57:17 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Authors: Keith Bostic, Chris G. Demetriou
|
||||
*
|
||||
* Permission to use, copy, modify and distribute this software and
|
||||
* its documentation is hereby granted, provided that both the copyright
|
||||
* notice and this permission notice appear in all copies of the
|
||||
* software, derivative works or modified versions, and any portions
|
||||
* thereof, and that both notices appear in supporting documentation.
|
||||
*
|
||||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
||||
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
*
|
||||
* Carnegie Mellon requests users of this software to return to
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
* School of Computer Science
|
||||
* Carnegie Mellon University
|
||||
* Pittsburgh PA 15213-3890
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
* 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 University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)autoconf.c 8.4 (Berkeley) 10/1/93
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -37,6 +54,12 @@
|
|||
|
||||
#include <machine/autoconf.h>
|
||||
|
||||
struct device *parsedisk __P((char *str, int len, int defpart, dev_t *devp));
|
||||
static struct device *getdisk __P((char *str, int len, int defpart,
|
||||
dev_t *devp));
|
||||
static int findblkmajor __P((struct device *dv));
|
||||
static int getstr __P((char *cp, int size));
|
||||
|
||||
/*
|
||||
* configure:
|
||||
* called at boot time, configure all devices on system
|
||||
|
@ -51,13 +74,7 @@ configure()
|
|||
panic("no mainbus found");
|
||||
(void)spl0();
|
||||
|
||||
#ifdef GENERIC
|
||||
if ((boothowto & RB_ASKNAME) == 0)
|
||||
setroot();
|
||||
setconf();
|
||||
#else
|
||||
setroot();
|
||||
#endif
|
||||
swapconf();
|
||||
cold = 0;
|
||||
}
|
||||
|
@ -67,12 +84,11 @@ configure()
|
|||
*/
|
||||
swapconf()
|
||||
{
|
||||
register struct swdevt *swp;
|
||||
register int nblks;
|
||||
struct swdevt *swp;
|
||||
int nblks, maj;
|
||||
|
||||
for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
|
||||
int maj = major(swp->sw_dev);
|
||||
|
||||
maj = major(swp->sw_dev);
|
||||
if (maj > nblkdev)
|
||||
break;
|
||||
if (bdevsw[maj].d_psize) {
|
||||
|
@ -83,62 +99,282 @@ swapconf()
|
|||
swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
|
||||
}
|
||||
}
|
||||
dumpconf();
|
||||
}
|
||||
|
||||
#define DOSWAP /* change swdevt and dumpdev */
|
||||
dev_t bootdev = 0; /* should be dev_t, but not until 32 bits */
|
||||
|
||||
static char devname[][2] = {
|
||||
'x','x', /* 0 = XX */
|
||||
'x','x', /* 1 = XX */
|
||||
'x','x', /* 2 = XX */
|
||||
'x','x', /* 3 = XX */
|
||||
'x','x', /* 4 = XX */
|
||||
'x','x', /* 5 = XX */
|
||||
'x','x', /* 6 = XX */
|
||||
'x','x', /* 7 = XX */
|
||||
's','d', /* 8 = sd */
|
||||
struct nam2blk {
|
||||
char *name;
|
||||
int maj;
|
||||
} nam2blk[] = {
|
||||
{ "st", 2 },
|
||||
{ "cd", 3 },
|
||||
{ "sd", 8 },
|
||||
#if 0
|
||||
{ "fd", XXX },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
findblkmajor(dv)
|
||||
struct device *dv;
|
||||
{
|
||||
char *name = dv->dv_xname;
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i)
|
||||
if (strncmp(name, nam2blk[i].name, strlen(nam2blk[0].name))
|
||||
== 0)
|
||||
return (nam2blk[i].maj);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static struct device *
|
||||
getdisk(str, len, defpart, devp)
|
||||
char *str;
|
||||
int len, defpart;
|
||||
dev_t *devp;
|
||||
{
|
||||
register struct device *dv;
|
||||
|
||||
if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
|
||||
printf("use one of:");
|
||||
for (dv = alldevs.tqh_first; dv != NULL;
|
||||
dv = dv->dv_list.tqe_next) {
|
||||
if (dv->dv_class == DV_DISK)
|
||||
printf(" %s[a-h]", dv->dv_xname);
|
||||
#ifdef NFSCLIENT
|
||||
if (dv->dv_class == DV_IFNET)
|
||||
printf(" %s", dv->dv_xname);
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return (dv);
|
||||
}
|
||||
|
||||
struct device *
|
||||
parsedisk(str, len, defpart, devp)
|
||||
char *str;
|
||||
int len, defpart;
|
||||
dev_t *devp;
|
||||
{
|
||||
register struct device *dv;
|
||||
register char *cp, c;
|
||||
int majdev, part;
|
||||
|
||||
if (len == 0)
|
||||
return (NULL);
|
||||
cp = str + len - 1;
|
||||
c = *cp;
|
||||
if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
|
||||
part = c - 'a';
|
||||
*cp = '\0';
|
||||
} else
|
||||
part = defpart;
|
||||
|
||||
for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
|
||||
if (dv->dv_class == DV_DISK &&
|
||||
strcmp(str, dv->dv_xname) == 0) {
|
||||
majdev = findblkmajor(dv);
|
||||
if (majdev < 0)
|
||||
panic("parsedisk");
|
||||
*devp = MAKEDISKDEV(majdev, dv->dv_unit, part);
|
||||
break;
|
||||
}
|
||||
#ifdef NFSCLIENT
|
||||
if (dv->dv_class == DV_IFNET &&
|
||||
strcmp(str, dv->dv_xname) == 0) {
|
||||
*devp = NODEV;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
*cp = c;
|
||||
return (dv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to find the device from which we were booted.
|
||||
* If we can do so, and not instructed not to do so,
|
||||
* change rootdev to correspond to the load device.
|
||||
*
|
||||
* XXX Actually, swap and root must be on the same type of device,
|
||||
* (ie. DV_DISK or DV_IFNET) because of how (*mountroot) is written.
|
||||
* That should be fixed.
|
||||
*/
|
||||
setroot()
|
||||
{
|
||||
int majdev, mindev, unit, part, adaptor;
|
||||
dev_t temp, orootdev;
|
||||
struct swdevt *swp;
|
||||
struct device *dv;
|
||||
register int len;
|
||||
dev_t nrootdev, nswapdev = NODEV;
|
||||
char buf[128];
|
||||
extern int (*mountroot) __P((void *));
|
||||
dev_t temp;
|
||||
struct device *bootdv, *rootdv, *swapdv;
|
||||
int bootpartition; /* XXX */
|
||||
#if defined(NFSCLIENT)
|
||||
extern char *nfsbootdevname;
|
||||
extern int nfs_mountroot __P((void *));
|
||||
#endif
|
||||
#if defined(FFS)
|
||||
extern int ffs_mountroot __P((void *));
|
||||
#endif
|
||||
|
||||
bootdv = NULL; /* XXX */
|
||||
bootpartition = 0; /* XXX */
|
||||
|
||||
/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
|
||||
if (boothowto & RB_DFLTROOT ||
|
||||
(bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
|
||||
return;
|
||||
majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
|
||||
if (majdev > sizeof(devname) / sizeof(devname[0]))
|
||||
return;
|
||||
adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
|
||||
part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
|
||||
unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
|
||||
mindev = (unit * MAXPARTITIONS) + part;
|
||||
orootdev = rootdev;
|
||||
rootdev = makedev(majdev, mindev);
|
||||
/*
|
||||
* If the original rootdev is the same as the one
|
||||
* just calculated, don't need to adjust the swap configuration.
|
||||
* If 'swap generic' and we couldn't determine root device,
|
||||
* ask the user.
|
||||
*/
|
||||
if (rootdev == orootdev)
|
||||
return;
|
||||
printf("changing root device to %c%c%d%c\n",
|
||||
devname[majdev][0], devname[majdev][1],
|
||||
unit, part + 'a');
|
||||
if (mountroot == NULL && bootdv == NULL)
|
||||
boothowto |= RB_ASKNAME;
|
||||
|
||||
#ifdef DOSWAP
|
||||
if (boothowto & RB_ASKNAME) {
|
||||
for (;;) {
|
||||
printf("root device");
|
||||
if (bootdv != NULL)
|
||||
printf(" (default %s%c)",
|
||||
bootdv->dv_xname,
|
||||
bootdv->dv_class == DV_DISK
|
||||
? bootpartition + 'a' : ' ');
|
||||
printf(": ");
|
||||
len = getstr(buf, sizeof(buf));
|
||||
if (len == 0 && bootdv != NULL) {
|
||||
strcpy(buf, bootdv->dv_xname);
|
||||
len = strlen(buf);
|
||||
}
|
||||
if (len == 4 && !strcmp(buf, "halt"))
|
||||
boot(RB_HALT);
|
||||
if (len > 0 && buf[len - 1] == '*') {
|
||||
buf[--len] = '\0';
|
||||
dv = getdisk(buf, len, 1, &nrootdev);
|
||||
if (dv != NULL) {
|
||||
rootdv = dv;
|
||||
nswapdev = nrootdev;
|
||||
goto gotswap;
|
||||
}
|
||||
}
|
||||
dv = getdisk(buf, len, bootpartition, &nrootdev);
|
||||
if (dv != NULL) {
|
||||
rootdv = dv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* because swap must be on same device type as root, for
|
||||
* network devices this is easy.
|
||||
*/
|
||||
if (rootdv->dv_class == DV_IFNET) {
|
||||
swapdv = NULL;
|
||||
goto gotswap;
|
||||
}
|
||||
for (;;) {
|
||||
printf("swap device");
|
||||
printf(" (default %s%c)", rootdv->dv_xname,
|
||||
rootdv->dv_class == DV_DISK?'b':' ');
|
||||
printf(": ");
|
||||
len = getstr(buf, sizeof(buf));
|
||||
if (len == 0) {
|
||||
switch (rootdv->dv_class) {
|
||||
case DV_IFNET:
|
||||
nswapdev = NODEV;
|
||||
break;
|
||||
case DV_DISK:
|
||||
nswapdev = MAKEDISKDEV(major(nrootdev),
|
||||
DISKUNIT(nrootdev), 1);
|
||||
break;
|
||||
case DV_TAPE:
|
||||
case DV_TTY:
|
||||
case DV_DULL:
|
||||
case DV_CPU:
|
||||
break;
|
||||
}
|
||||
swapdv = rootdv;
|
||||
break;
|
||||
}
|
||||
if (len == 4 && !strcmp(buf, "halt"))
|
||||
boot(RB_HALT);
|
||||
dv = getdisk(buf, len, 1, &nswapdev);
|
||||
if (dv) {
|
||||
if (dv->dv_class == DV_IFNET)
|
||||
nswapdev = NODEV;
|
||||
swapdv = dv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gotswap:
|
||||
rootdev = nrootdev;
|
||||
dumpdev = nswapdev;
|
||||
swdevt[0].sw_dev = nswapdev;
|
||||
swdevt[1].sw_dev = NODEV;
|
||||
} else if (mountroot == NULL) {
|
||||
int majdev;
|
||||
|
||||
/*
|
||||
* "swap generic"
|
||||
*/
|
||||
majdev = findblkmajor(bootdv);
|
||||
if (majdev >= 0) {
|
||||
/*
|
||||
* Root and swap are on a disk.
|
||||
*/
|
||||
rootdv = swapdv = bootdv;
|
||||
rootdev = MAKEDISKDEV(majdev, bootdv->dv_unit,
|
||||
bootpartition);
|
||||
nswapdev = dumpdev =
|
||||
MAKEDISKDEV(majdev, bootdv->dv_unit, 1);
|
||||
} else {
|
||||
/*
|
||||
* Root and swap are on a net.
|
||||
*/
|
||||
rootdv = swapdv = NULL;
|
||||
nswapdev = dumpdev = NODEV;
|
||||
}
|
||||
swdevt[0].sw_dev = nswapdev;
|
||||
swdevt[1].sw_dev = NODEV;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* `root DEV swap DEV': honour rootdev/swdevt.
|
||||
* rootdev/swdevt/mountroot already properly set.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rootdv->dv_class) {
|
||||
#if defined(NFSCLIENT)
|
||||
case DV_IFNET:
|
||||
mountroot = nfs_mountroot;
|
||||
nfsbootdevname = rootdv->dv_xname;
|
||||
return;
|
||||
#endif
|
||||
#if defined(FFS)
|
||||
case DV_DISK:
|
||||
mountroot = ffs_mountroot;
|
||||
printf("root on %s%c", rootdv->dv_xname,
|
||||
DISKPART(rootdev) + 'a');
|
||||
if (nswapdev != NODEV)
|
||||
printf(" swap on %s%c", swapdv->dv_xname,
|
||||
DISKPART(nswapdev) + 'a');
|
||||
printf("\n");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("can't figure root, hope your kernel is right\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the swap partition on the root drive the primary swap.
|
||||
*/
|
||||
temp = NODEV;
|
||||
for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
|
||||
if (majdev == major(swp->sw_dev) &&
|
||||
(mindev / MAXPARTITIONS)
|
||||
== (minor(swp->sw_dev) / MAXPARTITIONS)) {
|
||||
if (major(rootdev) == major(swp->sw_dev) &&
|
||||
DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) {
|
||||
temp = swdevt[0].sw_dev;
|
||||
swdevt[0].sw_dev = swp->sw_dev;
|
||||
swp->sw_dev = temp;
|
||||
|
@ -154,5 +390,50 @@ setroot()
|
|||
*/
|
||||
if (temp == dumpdev)
|
||||
dumpdev = swdevt[0].sw_dev;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
getstr(cp, size)
|
||||
register char *cp;
|
||||
register int size;
|
||||
{
|
||||
register char *lp;
|
||||
register int c;
|
||||
register int len;
|
||||
|
||||
lp = cp;
|
||||
len = 0;
|
||||
for (;;) {
|
||||
c = cngetc();
|
||||
switch (c) {
|
||||
case '\n':
|
||||
case '\r':
|
||||
printf("\n");
|
||||
*lp++ = '\0';
|
||||
return (len);
|
||||
case '\b':
|
||||
case '\177':
|
||||
case '#':
|
||||
if (len) {
|
||||
--len;
|
||||
--lp;
|
||||
printf("\b \b");
|
||||
}
|
||||
continue;
|
||||
case '@':
|
||||
case 'u'&037:
|
||||
len = 0;
|
||||
lp = cp;
|
||||
printf("\n");
|
||||
continue;
|
||||
default:
|
||||
if (len + 1 >= size || c < ' ') {
|
||||
printf("\007");
|
||||
continue;
|
||||
}
|
||||
printf("%c", c);
|
||||
++len;
|
||||
*lp++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue