Use new machine-independent setroot() and mountroothook code.

This commit is contained in:
thorpej 1997-01-31 02:07:29 +00:00
parent f159c829df
commit 801f7e1a0e
1 changed files with 21 additions and 416 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.65 1997/01/21 21:07:04 pk Exp $ */
/* $NetBSD: autoconf.c,v 1.66 1997/01/31 02:07:29 thorpej Exp $ */
/*
* Copyright (c) 1996
@ -103,15 +103,10 @@ extern int kgdb_debug_panic;
#endif
static int rootnode;
void setroot __P((void));
static char *str2hex __P((char *, int *));
static int getstr __P((char *, int));
static int findblkmajor __P((struct device *));
static struct device *getdisk __P((char *, int, int, dev_t *));
static int mbprint __P((void *, const char *));
static void crazymap __P((char *, int *));
int st_crazymap __P((int));
void swapconf __P((void));
void sync_crash __P((void));
int mainbus_match __P((struct device *, struct cfdata *, void *));
static void mainbus_attach __P((struct device *, struct device *, void *));
@ -123,18 +118,6 @@ static void bootpath_fake __P((struct bootpath *, char *));
static void bootpath_print __P((struct bootpath *));
int search_prom __P((int, char *));
/*
* The mountroot_hook is provided as a mechanism for devices to perform
* a special function if they're the root device, such as the floppy
* drive ejecting the current disk and prompting for a filesystem floppy.
*/
struct mountroot_hook {
LIST_ENTRY(mountroot_hook) mr_link;
struct device *mr_device;
void (*mr_func) __P((struct device *));
};
LIST_HEAD(, mountroot_hook) mrh_list;
/*
* Most configuration on the SPARC is done by matching OPENPROM Forth
* device names with our internal names.
@ -834,6 +817,16 @@ st_crazymap(n)
return prom_st_crazymap[n];
}
struct devnametobdevmaj sparc_nam2blk[] = {
{ "xy", 3 },
{ "sd", 7 },
{ "xd", 10 },
{ "st", 11 },
{ "fd", 16 },
{ "cd", 18 },
{ NULL, 0 },
};
/*
* Determine mass storage and memory configuration for a machine.
* We get the PROM's root device and make sure we understand it, then
@ -846,9 +839,9 @@ configure()
struct confargs oca;
register int node = 0;
register char *cp;
/* Initialize the mountroot_hook list. */
LIST_INIT(&mrh_list);
struct bootpath *bp;
struct device *bootdv;
int bootpartition;
/* build the bootpath */
bootpath_build();
@ -917,8 +910,14 @@ configure()
* Configure swap area and related system
* parameter based on device(s) used.
*/
setroot();
bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1];
bootdv = bp == NULL ? NULL : bp->dev;
bootpartition = bp == NULL ? 0 : bp->val[2];
setroot(bootdv, bootpartition, sparc_nam2blk);
swapconf();
dumpconf();
cold = 0;
}
@ -1742,400 +1741,6 @@ callrom()
promvec->pv_abort();
}
/*
* Configure swap space and related parameters.
*/
void
swapconf()
{
register struct swdevt *swp;
register int nblks;
for (swp = swdevt; swp->sw_dev != NODEV; swp++)
if (bdevsw[major(swp->sw_dev)].d_psize) {
nblks =
(*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
if (nblks != -1 &&
(swp->sw_nblks == 0 || swp->sw_nblks > nblks))
swp->sw_nblks = nblks;
swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
}
dumpconf();
}
#if 0 /* Unused */
dev_t bootdev;
#endif
#define PARTITIONMASK 0x7
#define PARTITIONSHIFT 3
struct nam2blk {
char *name;
int maj;
} nam2blk[] = {
{ "xy", 3 },
{ "sd", 7 },
{ "xd", 10 },
{ "st", 11 },
{ "fd", 16 },
{ "cd", 18 },
};
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, mindev, part;
if (len == 0)
return (NULL);
cp = str + len - 1;
c = *cp;
if (c >= 'a' && c <= 'h') {
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");
mindev = (dv->dv_unit << PARTITIONSHIFT) + part;
*devp = makedev(majdev, mindev);
break;
}
#ifdef NFSCLIENT
if (dv->dv_class == DV_IFNET &&
strcmp(str, dv->dv_xname) == 0) {
*devp = NODEV;
break;
}
#endif
}
*cp = c;
return (dv);
}
void
mountroot_hook_establish(func, dev)
void (*func) __P((struct device *));
struct device *dev;
{
struct mountroot_hook *mrhp;
mrhp = (struct mountroot_hook *)malloc(sizeof(struct mountroot_hook),
M_DEVBUF, M_NOWAIT);
if (mrhp == NULL)
panic("no memory for mountroot_hook");
bzero(mrhp, sizeof(struct mountroot_hook));
mrhp->mr_device = dev;
mrhp->mr_func = func;
LIST_INSERT_HEAD(&mrh_list, mrhp, mr_link);
}
/*
* 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.
*/
void
setroot()
{
register struct swdevt *swp;
register struct device *dv;
register int len, majdev, mindev;
dev_t nrootdev, nswapdev = NODEV;
char buf[128];
extern int (*mountroot) __P((void *));
dev_t temp;
struct mountroot_hook *mrhp;
struct device *bootdv;
struct bootpath *bp;
#if defined(NFSCLIENT)
extern char *nfsbootdevname;
extern int nfs_mountroot __P((void *));
#endif
#if defined(FFS)
extern int ffs_mountroot __P((void *));
#endif
bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1];
bootdv = bp == NULL ? NULL : bp->dev;
/*
* If `swap generic' and we couldn't determine boot device,
* ask the user.
*/
if (mountroot == NULL && bootdv == NULL)
boothowto |= RB_ASKNAME;
if (boothowto & RB_ASKNAME) {
for (;;) {
printf("root device ");
if (bootdv != NULL)
printf("(default %s%c)",
bootdv->dv_xname,
bootdv->dv_class == DV_DISK
? bp->val[2]+'a' : ' ');
printf(": ");
len = getstr(buf, sizeof(buf));
if (len == 0 && bootdv != NULL) {
strcpy(buf, bootdv->dv_xname);
len = strlen(buf);
}
if (len > 0 && buf[len - 1] == '*') {
buf[--len] = '\0';
dv = getdisk(buf, len, 1, &nrootdev);
if (dv != NULL) {
bootdv = dv;
nswapdev = nrootdev;
goto gotswap;
}
}
dv = getdisk(buf, len, bp?bp->val[2]:0, &nrootdev);
if (dv != NULL) {
bootdv = dv;
break;
}
}
/*
* because swap must be on same device as root, for
* network devices this is easy.
*/
if (bootdv->dv_class == DV_IFNET) {
goto gotswap;
}
for (;;) {
printf("swap device ");
if (bootdv != NULL)
printf("(default %s%c)",
bootdv->dv_xname,
bootdv->dv_class == DV_DISK?'b':' ');
printf(": ");
len = getstr(buf, sizeof(buf));
if (len == 0 && bootdv != NULL) {
switch (bootdv->dv_class) {
case DV_IFNET:
nswapdev = NODEV;
break;
case DV_DISK:
nswapdev = makedev(major(nrootdev),
(minor(nrootdev) & ~ PARTITIONMASK) | 1);
break;
case DV_TAPE:
case DV_TTY:
case DV_DULL:
case DV_CPU:
break;
}
break;
}
dv = getdisk(buf, len, 1, &nswapdev);
if (dv) {
if (dv->dv_class == DV_IFNET)
nswapdev = NODEV;
break;
}
}
gotswap:
rootdev = nrootdev;
dumpdev = nswapdev;
swdevt[0].sw_dev = nswapdev;
swdevt[1].sw_dev = NODEV;
} else if (mountroot == NULL) {
/*
* `swap generic': Use the device the ROM told us to use.
*/
majdev = findblkmajor(bootdv);
if (majdev >= 0) {
/*
* Root and swap are on a disk.
* val[2] of the boot device is the partition number.
* Assume swap is on partition b.
*/
int part = bp->val[2];
mindev = (bootdv->dv_unit << PARTITIONSHIFT) + part;
rootdev = makedev(majdev, mindev);
nswapdev = dumpdev = makedev(major(rootdev),
(minor(rootdev) & ~ PARTITIONMASK) | 1);
} else {
/*
* Root and swap are on a net.
*/
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.
*/
majdev = major(rootdev);
mindev = minor(rootdev);
goto gotroot;
}
switch (bootdv->dv_class) {
#if defined(NFSCLIENT)
case DV_IFNET:
mountroot = nfs_mountroot;
nfsbootdevname = bootdv->dv_xname;
return;
#endif
#if defined(FFS)
case DV_DISK:
mountroot = ffs_mountroot;
majdev = major(rootdev);
mindev = minor(rootdev);
printf("root on %s%c\n", bootdv->dv_xname,
(mindev & PARTITIONMASK) + 'a');
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.
*/
mindev &= ~PARTITIONMASK;
temp = NODEV;
for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
if (majdev == major(swp->sw_dev) &&
mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
temp = swdevt[0].sw_dev;
swdevt[0].sw_dev = swp->sw_dev;
swp->sw_dev = temp;
break;
}
}
if (swp->sw_dev != NODEV) {
/*
* If dumpdev was the same as the old primary swap device,
* move it to the new primary swap device.
*/
if (temp == dumpdev)
dumpdev = swdevt[0].sw_dev;
}
gotroot:
/*
* Find mountroot hook and execute.
*/
for (mrhp = mrh_list.lh_first; mrhp != NULL;
mrhp = mrhp->mr_link.le_next)
if (mrhp->mr_device == bootdv) {
(*mrhp->mr_func)(bootdv);
break;
}
}
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;
}
}
}
/*
* find a device matching "name" and unit number
*/