if (nswapdev == rootdev) nswapdev = NODEV;
char    *strchr __P((const char *, int));u_int      hexatoi __P((const char *));/* The following recursively searches a PROM tree for a given node */intsearch_prom(rootnode, name)        register int rootnode;        register char *name;{        register int rtnnode;        register int node = rootnode;        if (node == findroot() || !strcmp("hierarchical",                                          getpropstring(node, "device_type")))            node = firstchild(node);        if (!node)            panic("search_prom: null node");        do {                if (strcmp(getpropstring(node, "name"),name) == 0)                    return node;                if (node_has_property(node,"device_type") &&                    (!strcmp(getpropstring(node, "device_type"),"hierarchical")                     || !strcmp(getpropstring(node, "name"),"iommu"))                    && (rtnnode = search_prom(node, name)) != 0)                        return rtnnode;        } while ((node = nextsibling(node)));        return 0;}/* The following are used primarily in consinit() */intopennode(path)		/* translate phys. device path to node */	register char *path;{	register int fd;	if (promvec->pv_romvec_vers < 2) {		printf("WARNING: opennode not valid on sun4! %s\n", path);		return (0);	}	fd = promvec->pv_v2devops.v2_open(path);	if (fd == 0)		return 0;	return promvec->pv_v2devops.v2_fd_phandle(fd);}intnode_has_property(node, prop)	/* returns 1 if node has given property */	register int node;	register const char *prop;{	return ((*promvec->pv_nodeops->no_proplen)(node, (caddr_t)prop) != -1);}#ifdef RASTERCONSOLE/* Pass a string to the FORTH PROM to be interpreted */voidrominterpret(s)	register char *s;{	if (promvec->pv_romvec_vers < 2)		promvec->pv_fortheval.v0_eval(strlen(s), s);	else		promvec->pv_fortheval.v2_eval(s);}/* * Try to figure out where the PROM stores the cursor row & column * variables.  Returns nonzero on error. */intromgetcursoraddr(rowp, colp)	register int **rowp, **colp;{	char buf[100];	/*	 * line# and column# are global in older proms (rom vector < 2)	 * and in some newer proms.  They are local in version 2.9.  The	 * correct cutoff point is unknown, as yet; we use 2.9 here.	 */	if (promvec->pv_romvec_vers < 2 || promvec->pv_printrev < 0x00020007)		sprintf(buf,		    "' line# >body >user %lx ! ' column# >body >user %lx !",		    (u_long)rowp, (u_long)colp);	else		sprintf(buf,		    "stdout @ is my-self addr line# %lx ! addr column# %lx !",		    (u_long)rowp, (u_long)colp);	*rowp = *colp = NULL;	rominterpret(buf);	if (*rowp == *colp && *rowp != NULL)		panic("romgetcursor prom version");	return (*rowp == NULL || *colp == NULL);}#endifvoidromhalt(){	if (CPU_ISSUN4COR4M)		*promvec->pv_synchook = NULL;	promvec->pv_halt();	panic("PROM exit failed");}voidromboot(str)	char *str;{	if (CPU_ISSUN4COR4M)		*promvec->pv_synchook = NULL;	promvec->pv_reboot(str);	panic("PROM boot failed");}voidcallrom(){#if 0			/* sun4c FORTH PROMs do this for us */	if (CPU_ISSUN4)		fb_unblank();#endif	promvec->pv_abort();}/* * Configure swap space and related parameters. */voidswapconf(){	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;#endifstruct nam2blk {	char *name;	int maj;} nam2blk[] = {	{ "xy",		3 },	{ "sd",		7 },	{ "xd",		10 },	{ "st",		11 },	{ "fd",		16 },	{ "rd",		17 },	{ "cd",		18 },};static intfindblkmajor(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, unit, part;	if (len == 0)		return (NULL);	cp = str + len - 1;	c = *cp;	if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {		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);			unit = dv->dv_unit;			if (majdev < 0)				panic("parsedisk");			*devp = MAKEDISKDEV(majdev, 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);}voidmountroot_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. */voidsetroot(){	register struct swdevt *swp;	register struct device *dv;	register int len, majdev, unit, part;	dev_t nrootdev, nswapdev = NODEV;	char buf[128];	dev_t temp;	struct mountroot_hook *mrhp;	struct device *bootdv;	struct bootpath *bp;#if defined(NFSCLIENT)	extern char *nfsbootdevname;#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 = MAKEDISKDEV(major(nrootdev),					    DISKUNIT(nrootdev), 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.			 */			part = bp->val[2];			unit = bootdv->dv_unit;			rootdev = MAKEDISKDEV(majdev, unit, part);			nswapdev = dumpdev = MAKEDISKDEV(major(rootdev),			    DISKUNIT(rootdev), 1);		} else {			/*			 * Root and swap are on a net.			 */			nswapdev = dumpdev = NODEV;		}		if (nswapdev == rootdev)			nswapdev = 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);		unit = DISKUNIT(rootdev);		part = DISKPART(rootdev);		goto gotroot;	}	switch (bootdv->dv_class) {#if defined(NFSCLIENT)	case DV_IFNET:		mountroot = nfs_mountroot;		nfsbootdevname = bootdv->dv_xname;		return;#endif	case DV_DISK:		mountroot = dk_mountroot;		majdev = major(rootdev);		unit = DISKUNIT(rootdev);		part = DISKPART(rootdev);		printf("root on %s%c\n", bootdv->dv_xname,		    part + 'a');		break;	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) &&		    unit == DISKUNIT(swp->sw_dev)) {			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 intgetstr(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 */struct device *getdevunit(name, unit)	char *name;	int unit;{	struct device *dev = alldevs.tqh_first;	char num[10], fullname[16];	int lunit;	/* compute length of name and decimal expansion of unit number */	sprintf(num, "%d", unit);	lunit = strlen(num);	if (strlen(name) + lunit >= sizeof(fullname) - 1)		panic("config_attach: device name too long");	strcpy(fullname, name);	strcat(fullname, num);	while (strcmp(dev->dv_xname, fullname) != 0) {		if ((dev = dev->dv_list.tqe_next) == NULL)			return NULL;	}	return dev;}/* * The $#!@$&%# kernel library doesn't have strchr or atoi. Ugh. We duplicate * here. */char *strchr(p, ch)			/* cribbed from libc */	register const char *p, ch;{	for (;; ++p) {		if (*p == ch)			return((char *)p);		if (!*p)			return((char *)NULL);	}	/* NOTREACHED */}